home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / Mac Tech Notes (DocViewer) / TN-Text / TN-Text
Encoding:
Text File  |  1993-01-05  |  793.9 KB  |  2,001 lines  |  [ONLN/HLX2]

  1. The Appearance of Text
  2. Text        M.TE.Appearance
  3. Revised by:        March 1988
  4. Written by:    Ginger Jernigan    November 1986
  5. This technical note describes why text doesn’t always look the way you expect depending on the environment you are in.
  6. There are a number of Macintosh text editing applications where layout is critical.  Unfortunately, text on a newer machine sometimes prints differently than text on a 64K ROM Macintosh. Let’s examine some differences you should expect and why.
  7. The differences we will consider here are only differences in the layout of text lines (line layout), not differences in the appearance of fonts or the differences between different printers. Differences in line layout may affect the position of line, paragraph and page breaks. The four variables that can affect line layout are fonts, the printer driver, the font manager mode, and ROMs.
  8. Fonts
  9. Every font on a Macintosh contains its own table of widths which tells QuickDraw how wide characters are on the screen. For every style point size there is a separate table which may contain widths that vary from face to face and from point size to point size. Character widths can vary between point sizes of characters even in the same face. In other words, fonts on the screen are not necessarily linearly scalable.
  10. Non-linearity is not normally a problem since most fonts are designed to be as close to linear as possible. A font face in 6 point has very nearly the same scaled widths of the same font face in 24 point (plus or minus round-off or truncation differences). QuickDraw, however, requires only one face of any particular font to be in the System file to use it in any point size. If only a 10 point face actually exists, QuickDraw may scale that face to 9, 18, 24 (or whatever point size) by performing a linear scale of the 10 point face. 
  11. This can cause problems. Suppose a document is created on one Macintosh containing a font that only exists in that System file in one point size, say 9 point. The document is then taken to another Macintosh with a System file containing that same font but only in 24 point. The document may, in fact, appear differently on the two screens, and when it is printed, will have line breaks (and thus paragraph and page breaks) occurring in different places simply because of the differences in character widths that exist between the 9 point and 24 point faces.
  12. The Printer Driver
  13. Even when the printer you are using has a much higher resolution than what the screen can show, printer drivers perform line layout to match the screen layout as closely as possible.
  14. The line layout performed by printer drivers is limited to single lines of text and does not change line break positions within multiple lines. The driver supplies metric information to the application about the page size and printable area to allow the application to determine the best place to make line and page breaks.
  15. Printer driver line layout does affect word spacing, character spacing and even word positioning within a line. This may affect the overall appearance of text, particularly when font substitutions are made or various forms of page or text scaling are involved. But print drivers NEVER change line, paragraph or page break positions from what the application or screen specified. This means that where line breaks appear on the screen, they will always appear in the same place on the printer regardless of how the line layout may affect the appearance within the line.
  16. Operating System and ROMs
  17. In this context, operating system refers to the ROM trap routines which handle fonts and QuickDraw. Changes have occurred between the ROMs in the handling of fonts. Fonts in the 64K ROMs contain width tables (as described above) which are limited to integer values. Several new tables, however, have been added to fonts for the newer ROMs. The newer ROMs add an optional global width table containing fractional or fixed point decimal values. In addition, there is another optional table containing fractional values which can be scaled for the entire range of point sizes for any one face. There is also an optional table which provides for the addition (or removal) of width to a font when its style is changed to another value such as bold, outline or condensed. It is also possible, under the 128K ROMs, to add fonts to the system with inherent style properties containing their own width tables that produce different character widths from derived style widths.
  18. One or all of the above tables may or may not be invoked depending on, first, their presence, and second, the mode of the operating system. The Font Manager in the newer ROMs allows the application to arbitrarily operate in either the fractional mode or integer mode (determined, in most cases, by the setting of FractEnable) as it chooses, with the default being integer. There is one case where fractional widths will be used if they exist even though fractional mode is disabled. When FScaleDisable is used fractional widths are always used if they exist regardless of the setting of FractEnable.
  19. Differences in line layout (and thus line breaks) may be affected by any combination of the presence or absence of the optional tables, and the operating mode, either fractional or integer, of the application. Any of the combinations can produce different results from the original ROMs (and from each other).
  20. The integer mode on the newer ROMs is very similar to, but not exactly the same as, the original 64K ROMs. When fonts with the optional tables present are used on Macintoshes with 64K ROMs, they continue to work in the old way with the integer widths. However, on newer ROMs, even in the integer mode, there may be variations in line width from what is seen on the old ROMs. In the plain text style there is very little if any difference (except if the global width table is present), but as various type styles are selected, line widths may vary more between ROMs.
  21. Variations in the above options, by far, account for the greatest variation in the appearance of lines when a document is transported between one Macintosh and another. Line breaks may change position when documents created on one system (say a Macintosh) are moved to another system (like a Macintosh Plus). Variations are more pronounced as the number and sizes of various type styles increase within a document.
  22. In all cases, however, a printer driver will produce exactly the same line breaks as appear on the screen with any given system combination.
  23. Further Reference:
  24. •    The Printing Manager
  25. •    The Font Manager
  26. •    M.IM.LaserWriterOpt
  27. Script Manager 2.0 Date & Time Problems
  28. Text        M.TE.ScriptDateTime
  29. Written by:    John Harvey    February 1990
  30. This Technical Note describes known bugs and features in and solutions to the date and time routines introduced in Script Manager 2.0.
  31. From the beginning, the Macintosh’s ability to handle dates was limited to a rather small range—slightly more than a century.  Enhancements to the Script Manager, introduced with System Software 6.0, extended this range to ±35,000 years.  Unfortunately, there is a minor bug in one of the crucial calls and a “feature” that looks like a bug in another.
  32. You Said It Would Be A Long Time
  33. _LongSecs2Date, the routine that translates a LongDateTime to a LongDateRec, has a bug caused by using a variable that has not been properly initialized.  This bug rears its ugly head when negative values are passed to the routine.  System Software 6.0.4 and later fix this bug, and there is a simple solution for earlier systems.
  34. If using System Software 6.0.3 and earlier, if you call _LongSecs2Date once before you really want to use it, the variable is cleared.  After the initial call, _LongSecs2Date works correctly.
  35. For example:
  36. MPW Pascal
  37. PROCEDURE DoDateStuff;
  38. VAR
  39.   lsecs: LongDateTime;
  40.   ldr:   LongDateRec;
  41. BEGIN
  42.   InitDateCache(dcr);
  43.   lsecs := 0;
  44.   LongSecs2Date(lsecs,ldr);
  45.   {now you can call LongSecs2Date for real}
  46. END;
  47. MPW C
  48. void DoDateStuff()
  49. {
  50.   LongDateTime lsecs;
  51.   LongDateRec  ldr;
  52. /* work around the bug */
  53.   lsecs = 0;
  54.   LongSecs2Date(&lsecs,&ldr);
  55. /* now call LongSecs2Date for real */
  56. }
  57. Any String To Date
  58. The routine _String2Date was originally designed to be as forgiving as possible.  It is so forgiving that it accepts any non-alphabetic character as a separator and accepts a single number as a valid date.  For instance, if you pass _String2Date a string like “<20” it generously assumes that the less than sign (<) is intended as a divider and that “20” must be intended as a day, since there are only 12 months in a year.  It returns a result of noErr and a date which is the twentieth of the current month in the current year.  The string “<3*3” produces March 3 of the current year, while “4>1” politely gives the date April 1 of the current year.
  59. This forgiveness really is not a bug, but a feature.  Unfortunately it isn’t a feature that has been greatly appreciated in the developer community.  For that reason, the rules for date and time dividers are tighter in System 7.0.  Current thinking is that all list separators now used in 'itl0' resources will be allowed with a few common date separators used in the U.S. (e.g., colon (:) and hyphen (-)).  For now, it is important to be aware of, shall we say, the flexibility of _String2Date and avoid thinking of it as an intelligent date parser.  If you want to parse something, you can use _IntlTokenize.
  60. Further Reference:
  61. •    Inside Macintosh, Volume V, The Script Manager
  62. •    The Script Manager 2.0, Interim Chapter (DTS)
  63. Drawing Characters into a Narrow GrafPort
  64. Text        M.TE.TextInNarrowGP
  65. Revised by:        March 1988
  66. Written by:    Ginger Jernigan    January 1986
  67. When you draw a character into a GrafPort, your program will die with an address error if the width of the GrafPort is smaller than the width of the character. If you check before drawing the character to see if the GrafPort is wide enough, you can avoid this unfortunate tragedy.
  68. Further Reference:
  69. •    QuickDraw
  70. Fond of FONDs
  71. Text        M.TE.FONDs
  72. Written by:         Joseph Maurer     May 1992
  73. This Technical Note takes the place of Tech Note #26, “Character vs. String Operations in QuickDraw” by Bryan Stearns (March 1988), which pointed out the possible differences between the results of a StringWidth call and successive calls to CharWidth. This Note updates and brings into a broader context the issues related to text measuring. It also provides additional documentation on font family resources ('FOND's), and addresses various other frequently asked questions related to the Font Manager. 
  74. Introduction
  75. Every Macintosh developer needs to draw text in a GrafPort, and to specify typeface, size, and style. In most cases, there are no problems, and application developers don’t need to have in-depth knowledge of the Font Manager’s inner workings and the data structures involved. Sometimes, however, the results on the screen or on printed output may be different from what you expected. Then, usually, DTS comes into play to figure out what the problem is and how to fix it. This Note is based on sharp developer questions from the last year or so, which point mainly at shortcomings of the existing Font Manager architecture, inconsistencies in its data structures, and missing details in the documen-tation.
  76. We’ll start with a historical overview, which discusses the introduction of font family description resources ('FOND's) back in 1986, explains the consequences of non-proportionally scaling fonts, and covers  non-registration and volatility of font family numbers.
  77. We will then deal with the Font/DA Mover and the built-in “Mover” of the Finder in System 7. We discuss a number of not-so-well-known aspects of moving fonts in and out of a suitcase file, and recommend that you altogether abandon the resource type 'FONT'. We'll also comment on font names, and show you how to put separate stylistic variants of a typeface together into one font family. And we provide documentation on the ffVersion field of a 'FOND' (accompanied by a disclaimer and another piece of irritating information).
  78. The main body of this Note addresses how the Font Manager works in the FMSwapFont context, and gives information on the scaling factors in the FMOutput structure and on the changes introduced by TrueType. We again took the examples of unexpected behavior (under certain circumstances) from developer questions. Thanks for helping document this!
  79. Determining the width of text, as required for line layout, is sometimes trickier than you might think. We will document the effects of SetFractEnable in more detail and mention some more line layout problems.
  80. Finally, this Note includes sample code that puts the OutlineMetrics call to work, and  determines text bounding boxes for bitmap fonts.
  81. Some FOND Background 
  82. Originally (Inside Macintosh Volume I, Chapter 7), all font-related data was contained in resources of type 'FONT'. For a font number within the range 0....255, and a font size restricted to less than 128, the (unnamed) 'FONT' resource with an ID:
  83.     128*(font number) + (font size)
  84. contained the bitmap font strike, while the 'FONT' resource with ID = 128*(font number), corresponding to font size 0, did not contain any data, but its resource name provided the font family name. QuickDraw took care of stylistic variants like italic, bold, shadow, and so on; if a user had a specifically fine-tuned font strike for a stylistic variant, QuickDraw would not automatically substitute it when drawing text.
  85. For aesthetic reasons, bitmap fonts for different sizes were usually designed with widths non-proportional to the point size. For example, the text “Show the difference in text widths” drawn with Courier 9 measures 170 pixels, whereas the same text drawn with Courier 18 measures 374 pixels, which is 10% more than you expect. (By the way, this is bad news for the ImageWriter printer driver. When “Best” mode (144 dpi) is selected and text in Courier 9 is to be printed, the printer driver uses Courier 18 to render the 9-point font size on the paper at twice the screen resolution, and obviously has big trouble compensating for the 10% difference in text width.)
  86. On the other hand, given that only integer character widths (in QuickDraw’s 72 dpi units) are possible, proportional font scaling is compromised anyway.  Accumulated rounding errors in text measuring, particularly for scaled fonts, contribute to the headaches of many Macintosh programmers. The computed text widths (vital for positioning text precisely and for line layout algorithms to justify text) sometimes change quite abruptly when the user removes or adds certain font sizes.
  87. The introduction of the LaserWriter, and the success of Macintosh in the desktop publishing arena,  required an extension of the original Font Manager architecture. This extension is based on the concept of “font family description” resources of type 'FOND', and on a new resource type 'NFNT' for the data of the existing 'FONT' resources (see Inside Macintosh Volume IV, Chapter 5).
  88. The 'FOND' resource stores size-independent information about the font family, and its resource ID is the font number (in the range 0...32767). The resource name of the 'FOND' is the font name, and it contains a variable-length font association table, which references the font strikes belonging to a specific font family. These references include size, style, and resource ID of the 'NFNT' or 'FONT' resource containing the bitmap font data. TrueType fonts were retrofitted into this scheme, and are identified as font strike resources for point size zero.  Any reference to point size zero refers to a resource of type 'sfnt'.
  89. Note:    The range 0...32767 for font numbers is subdivided into ranges for the various script systems (see Inside Macintosh Volume VI, pages 13-8 and 14-22, and M.TE.FontsAndScripts). This restricts the range of font numbers for the Roman script to 0...16383, with 0, 1, and 16383 reserved for the system. 
  90.     Since Apple originally intended fonts to be referenced by their font family numbers, DTS attempted to register those numbers (see Inside Macintosh Volume I, page 219 and Volume IV, page 31).  This failed—not only because the number of fonts registered grew greater than the number of font family numbers available, but also because the Font/DA Mover (version 3.8, shipped with System 6), and the “Mover” built into the System 7 Finder resolve conflicts between font IDs (which happened anyway!) by renumbering the fonts on-the-fly. There is no font ID registration any more—except for the very special case of Japanese Kanji 'FOND'–'fbit' IDs, and potentially for Korean, Chinese and other double-byte fonts.
  91.     As early as April 1988, M.IM.FontNames recommended the use of font names rather than font family numbers.  Since then, the recommendation has been reinforced in Inside Macintosh Volume VI, page 12-16. Fortunately, most applications have been good about following this recommendation. Unfortunately, some exceptions remain, even in Apple’s own software. QuickDraw Pictures created without 32-Bit QuickDraw refer to fonts by font family number only! 
  92. For obvious reasons of upward compatibility (to maintain existing fonts, and to avoid reflowing of existing documents), the introduction of 'FOND's did not solve all the problems. This is what this Note is all about.
  93. Moofing Fonts
  94. The Font/DA Mover utility has evolved into version 4.1, which knows about 'sfnt's. It is available on the Developer CD Series  disc, path “Tools & Apps (Moof!): Misc. Utilities:”. The Finder in System 7 incorporates its own “Mover” (see Inside Macintosh Volume VI, page 9-33), which makes the Font/DA Mover redundant for System 7 users.
  95. Given the combinatorial explosion of all imaginable situations with 'FOND's, 'FONT's, 'NFNT's and 'sfnt's, and stylistic variations of fonts belonging to the same family, the font moving job deserves respect. The following notes cover some less well-known aspects of this business.
  96. •    If an old “standalone” 'FONT' (without corresponding 'FOND' resource) is moved into a suitcase file, Font/DA Mover or the System 7 Mover creates a minimal 'FOND' resource on-the-fly. This 'FOND' has no tables, and nearly all its fields are zeroed. The System 7 Finder also converts the resource type from 'FONT' to 'NFNT';  unfortunately, the Font/DA Mover keeps the resource type 'FONT'.
  97. Note:    While it is perfectly legal to have 'FOND's continue to reference the older 'FONT' type, DTS recommends that you avoid 'FONT's. Accessing 'FONT's is much slower, since the Font Manager always looks for 'FOND's and 'NFNT's first. More importantly, 'FONT's are troublemakers if an application comes with its own font in its resource fork. Imagine an application that includes a private 'FOND' which references a 'FONT' in its resource fork by resource ID. When the Font Manager wants to load the font resource, it first looks for a resource of type 'NFNT' with this same resource ID. If there’s an 'NFNT' in the System file with the same resource ID, the Font Manager will pick it instead of the 'FONT' from the application’s resource fork.  This happens more often than you’d like to think!
  98. •    Under the current font architecture, the font name is the resource name of the 'FOND' resource (let’s forget about 'FONT's altogether), so the font name can be any Pascal string. Unfortunately, this conflicts with the 31-character limitation of a file name when the System 7 Finder derives the file name of a movable font file (Inside Macintosh Volume VI, page 9-34) from the font name. Some third-party fonts come with font names long enough to cause trouble.  You may also see this problem when trying to open a suitcase if the Finder can't generate distinct names for all of the fonts in the suitcase; the Finder may say the suitcase is “damaged” when it is not.
  99. Note:    Each TrueType 'sfnt' resource contains a Naming Table (see The TrueType™ Font Format Specification, APDA™ M0825LL/A) which provides nearly unrestricted font naming capabilities, to accommodate the needs of font manufacturers. A forthcoming Macintosh Technical Note on TrueType Naming Tables gives additional information.
  100. •    QuickDraw and the current Font Manager have no provision for stylistic variants like “light,” “medium,” “demi,” “book,” “black,” “heavy,” “extra,” “ultra,” etc., used in the context of professional typesetting. Therefore, each of these variants comes with a separate font family resource. Probably for reasons of consistency, the “italic” variants have their own font family resources as well. Unfortunately, unless each 'FOND' references both the “plain” and the “italic” font strikes, QuickDraw will no longer know a customized italic font strike exists.
  101.     It is fairly easy, using System 7 and ResEdit, to merge two font families (named, for exmaple, “myFont” and “myFont italic”) into one.  This way, QuickDraw will automatically use the pre-designed italic font strike instead of creating one algorithmically.  Follow these convenient steps: 
  102. 1.    Make sure there is no resource ID conflict between the 'NFNT's and 'sfnt's belonging to both families.
  103. 2.    Make sure the style bits for italic are set in the font association table of “myFont italic.”
  104. 3.    From ResEdit’s File menu, “Get Info...” on the “myFont” 'FOND' resource.  Write down the resource ID of the “myFont” 'FOND'.
  105. 4.    From ResEdit’s File menu, “Get Info...” on the “myFont italic” 'FOND'.  Change its resource ID to be identical to the one you wrote down in step 3.  Change its resource name to “myFont.”
  106. 5.    Use the Finder in System 7 to move the contents of the “myFont italic” suitcase into the original “myFont” suitcase. It will merge all constituents into one font association table, and thus enable transparent substitution of the right font for QuickDraw’s italic style.
  107. Version Numbers
  108. The 'FOND' structure (see Inside Macintosh Volume IV, page 45, “FamRec”) contains a field ffVersion, and inquiring minds naturally want to know more about it. Before anything else, however, please read the following disclaimer:
  109. Disclaimer:    The Font Manager does not check version numbers in a 'FOND', and we recommend that you not rely on the (intentionally vague) statements below, but rather analyze the data in the 'FOND'independently.
  110. Currently, values 0...3 may appear in the ffVersion field, with the following intended interpretations:
  111. Version 0:    Usually indicates that the 'FOND' has been created on the fly by the Font/DA Mover (or the System 7 Finder). But the 'FOND' for Palatino on the distribution disks of System 7 is a counterexample.
  112. Version 1:    Obviously indicates the first version when 'FOND's came out (Inside Macintosh Volume IV, page 36).
  113. Version 2:    Corresponds to the extension of the 'FOND' format documented in Inside Macintosh Volume V, page 185 (which does not mean that the 'FOND' actually contains a bounding box table).
  114. Version 3:    The 'FOND' is supposed to contain a bounding box table.
  115. This brings up an annoying fact.  All measurement values (referring to a hypothetical 1-point font) in the 'FOND' are in a 16-bit fixed-point format, with an integer part in the high-order 4 bits and a fractional part in the low-order 12 bits. You would expect that negative values (like for ffDescent, or in the kerning tables) are represented in the usual two’s-complement format, such that standard binary arithmetic applies. This is mostly true, but not always. Again, Palatino is a counterexample (and probably not the only one). To our knowledge, version 0 and version 1 'FOND's have negative values represented in a format where the most significant bit is the sign bit, and the rest represents the absolute value.  However, there is nothing in the system software that enforces this, so counterexamples may exist.
  116. Warning:    Don’t rely on the version number, but include sanity checks for the negative values in a 'FOND' instead!  The following Pascal function shows how this can be done:
  117.     FUNCTION Check4p12Value(n: Integer): Integer;
  118.     { n is a 4.12 fixed-point value; i.e., its "real" value is n/4096.    }
  119.     { If n is "unreasonably negative," interpret the most significant bit }
  120.     { as sign bit, and convert to the usual two's complement format.      }
  121.        BEGIN
  122.           IF n < $8FFF THEN { means: (4.12-interpretation of n) is below - 7 }
  123.              Check4p12Value := - BitAnd(n,$7FFF)
  124.          { i.e., mask sign bit, and take negative of absolute value }
  125.           ELSE
  126.              Check4p12Value := n;
  127.        END;
  128. In the Heart of the Font Manager
  129. Swapping Fonts
  130. As stated in Inside Macintosh, there is only one contact between QuickDraw and the Font Manager: the FMSwapFont function. Each of the three QuickDraw text measuring functions (CharWidth, StringWidth and TextWidth) always ends up in the QuickDraw bottleneck procedure QDProcs.txMeasProc. Each of the three QuickDraw text drawing procedures (DrawChar, DrawString and DrawText)  always ends up in the QDProcs.textProc bottleneck procedure. Any reasonable textProc (like StdText) needs to call the currently-installed text measuring bottleneck procedure before actually rendering the text. And what does any reasonable text measuring bottleneck procedure(like StdTxMeas) do first, before anything else? It calls FMSwapFont, to make sure we are talking about the right font and its properties! (To be precise, GetFontInfo and FontMetrics are the other calls that make sure the right font is swapped in and set up, without requiring you to call FMSwapFont explicitly.)
  131. Responding to a font request is a lot of work, and FMSwapFont has been optimized to return as quickly as possible if the request is the same as the previous one. Building the global width table (see Inside Macintosh Volume IV, page 41) is among the more time-consuming tasks related to FMSwapFont; this is why the Font Manager maintains a cache of up to 12 width tables.
  132. Inside Macintosh Volume I, page 220 documents the Font Manager’s choice when a font of the requested size is not available.  However, some consequences or additional features have occasionally been a surprise to developers (and users as well).
  133. Scaling Factors in FMOutPut and StdTxMeas
  134. Let’s suppose you have only a 12-point bitmap version of Palatino, and don’t have any Palatino outline fonts. When you request Palatino 18, QuickDraw sets up the FMInput record with size = 18 and numer = denom = Point($00010001).On return, the FMOutput record contains the handle to the font record to use (the 'NFNT' with the Palatino 12 bitmap font strike), and indicates the scaling factors QuickDraw will have to use to produce the desired text point size in FMOutput.numer and FMOutput.denom. In this example, that ratio is 3/2.
  135. Note that these are also the values returned in StdTxMeas (Inside Macintosh Volume I, page 199) if you call the procedure with numer = denom = Point($00010001).  Why?  Because StdTxMeas calls FMSwapFont, as explained under “Swapping Fonts.”  StdTxMeas does not apply these scaling factors to the text it measures. In our example, it would measure Palatino 12 and return numer and denom  in the ratio 3/2 to tell you that your application must multiply the results by these values to get the correct measurements for Palatino 18.  This has surprised more than one programmer who didn’t expect numer and denom to change!
  136. By the way, the Font Manager always normalizes the scaling factors as fractions numer/denom such that the denominator is equal to 256.  In our example, the real numbers returned by FMSwapFont or StdTxMeas are numer = 384 and denom = 256.
  137. Warning:    If the scaling factors numer and denom passed to StdTxMeas, StdText (see Inside Macintosh Volume I, pages 198 and 199), or in the FMInput record to FMSwapFont are such that txSize*numer.v/denom.v is less than 0.5 and rounds to 0, and if there is more than one 'sfnt' resource referenced in the font association table, then the current Font Manager may get confused and return results for the wrong font strike.
  138. TrueType Always Has the Right Size
  139. The default value of outlinePreferred is FALSE. If you have bitmap fonts for Palatino 12 and Palatino 14 in your system as well as a Palatino TrueType font, then requests for Palatino 12 or Palatino 14 are fulfilled with the bitmap fonts, but requests for any other size are fulfilled with the TrueType font. In particular, if you (or, for example, a printer driver) need Palatino 12 scaled by 2, the Font Manager will actually look for Palatino 24 and return the outline font, regardless of the setting of outlinePreferred. Even if you wanted the bitmap font doubled for exact “what-you-see-is-what-you-get” text placement, you’re out of luck—you get the TrueType font, which may have very different font metrics or character shapes.
  140. If the Font Manager uses an outline font to fulfill a given font request, the IsOutline function returns TRUE. Interestingly, this does not imply that RealFont returns TRUE as well. If the text size is smaller than the value lowestRecPPEM (“smallest readable size in pixels”) in the 'head' font header in the TrueType font (see The TrueType Font Format Specification, version 1.0, page 227),  then RealFont returns FALSE!
  141. First Size, Then Style—or: To Be or Not to Be Outline
  142. When the Font Manager walks the font association table of a 'FOND' to look for a font strike of a specified size and style, it stops at the first font of the right size. Only if you requested a stylistic variant (like bold or italic) does it take a closer look at the fonts of the same size.  It does this by putting weights on the various style bits (for example, 8 for italic, 4 for bold, 3 for outline) and choosing the font strike whose style weight most closely matches the weight of the requested style. All this is fine when only bitmap fonts are available. With the presence of TrueType outlines, however, the results are not always as expected, depending on the font configuration installed. 
  143. Let’s look at a few examples:
  144. Example 1:    Let’s suppose you have the bitmap font Times 12 (Normal) and the TrueType fonts Times (Normal), Times Italic and Times Bold in your system. If you request Times 14 Italic or Times 14 Bold, it’s rendered from the Times Italic or Times Bold TrueType fonts.  However, if you ask for Times 12 Italic or Times 12 Bold, and your system has the default setting of outlinePreferred = FALSE, the Font Manager decides to take the Times 12 bitmap and let QuickDraw algorithmically slant it (for italics) or smear it (for bold).
  145.     
  146. Example 2:    Let’s suppose you want to draw big, bold Helvetica characters and there are no existing bitmaps for the size you want. If the Helvetica Bold TrueType outlines are available, the Font Manager chooses them and the only surprise in text rendering will be a pleasant one. If there is no Helvetica Bold TrueType font, however (like in the machine of your customer, who kept only the normal Helvetica TrueType font in his system), then the characters are rendered using the normal Helvetica outlines and, in a second step, QuickDraw applies its horizontal 1-pixel “smearing” to simulate the bold stylistic variant. The result is very different (and rather an unpleasant surprise).
  147. Example 3:    Admittedly, this is less likely (but it has happened). Let’s suppose somebody decides to rip the Times TrueType outline out of the System file (don’t  ask me why—I don’t  know). He forgets to take the Times Italic TrueType outline away as well. The next time he draws text in Times (Normal), in a size for which there is no bitmap font (or if outlinePreferred = TRUE), the Font Manager goes for an 'sfnt', and the text shows up in italic  (what a surprise!).
  148. Unfortunately, given the current implementation of the Font Manager, there are no solutions to the problems illustrated above—other than asking users of your application to install the fonts you recommend. The only way to anticipate these potential surprises from within your application is to look into the 'FOND's font association table. You can’t depend on the IsOutline function because it returns TRUE as soon as the Font Manager stops at an 'sfnt', in its first pass through the font association table—regardless of subsequent stylistic variations.  This means, for example, if you ask for Helvetica Bold and IsOutline returns TRUE, you don’t know if you got the Helvetica Bold TrueType font or if QuickDraw “smeared” the Helvetica (Plain) TrueType font.
  149. Where Do the Widths Come From?
  150. Text measuring (for example, for precise text placement in forms with bounding boxes) and most line layout algorithms for justified text rely heavily on the character widths contained in the global width table. Given that under the current font architecture, we may easily have three or more different width tables for the same font specification (the non-proportional integer widths attached to the 'NFNT', the fractional widths contained in the 'FOND', and the fractional widths provided by the 'sfnt'), it is important to understand where the widths come from in any case.
  151. Since SetFractEnable was introduced (Inside Macintosh Volume IV, page 32 and Volume V, page 180), its setting TRUE or FALSE was supposed to give predictable effects. If it’s FALSE, the Font Manager takes the integer widths from the 'NFNT'; if it’s TRUE, it takes the fractional widths from the 'FOND'. Unfortunately, there are some additional details and side effects that are not well known.
  152. •    The Font Manager looks at bit 14 of the ffFlags field in the 'FOND' (see Inside Macintosh Volume IV pages 36 and 37). If it is set (like it is for Courier), the fractional widths from the 'FOND' are never  used.
  153. •    If SetFractEnable is TRUE and you request a stylistic variation like bold or italic, the Font Manager looks at bits 12 and 13 of the ffFlags field to decide how different widths or extra widths for the stylistic variants have to be used.  What it decides is documented in the “Font Manager” chapter of Inside Macintosh Preview, located on the Developer CD Series discs.
  154. •    Given that it is not possible to set the pen to a fractional position, precise text positioning with fractional widths enabled is always compromised because of (accumulated) rounding errors.
  155. •    QuickDraw distributes the accumulated rounding errors across characters within a string (instead of adding it at the end of the drawn text). This results in poor text quality on the screen, and in problems when calculating the position of the insertion point between characters.
  156. •    The LaserWriter driver watches what you pass to SetFractEnable. Passing TRUE to SetFractEnable disables some of the LaserWriter driver’s line layout features, assuming that the programmer intends to control text placement manually.  Explicitly passing FALSE to SetFractEnable achieves different results than using the default value of FALSE—Font Substitution behaves differently, for example.  These effects are sometimes Not What You Wanted.
  157. •    On non-32-Bit-QuickDraw systems, SetFractEnable is not recorded in pictures. This affects the line layout of text reproduced through DrawPicture if the picture was created with fractional widths enabled.
  158. In systems with TrueType, quite naturally  the widths always come from the 'sfnt' when the Font Manager uses a TrueType font.  If fractEnable is FALSE, hand-tuned integer character widths for specific point sizes come from the 'hdmx' table in the 'sfnt'.  If fractEnable is FALSE and no 'hdmx' table is present or it contains no entries for the desired point size, the fractional character widths from the 'sfnt' are rounded to integral values.
  159. More Line Layout Problems
  160. The routines SpaceExtra (Inside Macintosh Volume I, page 172) and CharExtra (Inside Macintosh Volume V, page 77; available only in color GrafPorts) are intended to help you draw fully justified text. This works fine on the screen, but not all printer drivers are smart enough to use these settings appropriately under all circumstances. In particular, if you pass TRUE to SetFractEnable, or if you turn the LaserWriter driver’s line layout algorithm off (by means of the picture comment LineLayoutOff; see Macintosh Technical Note #91), or if font substitution is enabled and actually occurs, it is better not to rely on SpaceExtra and CharExtra when printing fully justified text. Instead, keep the LaserWriter driver’s line layout adjustments off, and calculate the placement of your text (word by word, or even character by character) yourself.
  161. Putting Text Into Boxes
  162. TrueType fonts came to the Macintosh together with seven new Font Manager routines (as documented in Inside Macintosh Volume VI, Chapter 12). The OutlineMetrics function is certainly the most sophisticated of these, and sample code illustrating its usage may be helpful. The following procedure DrawBoxedString assumes that the new outline calls (Inside Macintosh Volume VI, Chapter 12) are available, and that IsOutline returns TRUE for the current port setting.
  163. PROCEDURE DrawBoxedString(pt: Point; s: Str255);
  164. { Draw string s at pen position (pt.h, pt.v), and show each character's bounding box. }
  165.    CONST
  166.       kOneOne = $00010001;
  167.    VAR
  168.       advA: FixedPtr;
  169.       lsbA: FixedPtr;
  170.       bdsA: RectPtr;
  171.       err,i,yMin,yMax,leftEdge,temp: Integer;
  172.       numer,denom: Point;
  173.       advance,lsb: Fixed;
  174.       r: Rect;
  175.    BEGIN
  176.       numer := Point(kOneOne);
  177.       denom := Point(kOneOne); { unless you want to draw with scaling factors
  178.                                 .... }
  179.       MoveTo(pt.h,pt.v);
  180.       DrawString(s);
  181. { This is for the pleasure of your eyes only — in practice, you would probably }
  182. { first look at the metrics, and then decide where and how to draw the string! }
  183.       advA := FixedPtr(NewPtr(Length(s) * SizeOf(Fixed)));
  184.       lsbA := FixedPtr(NewPtr(Length(s) * SizeOf(Fixed)));
  185.       bdsA := RectPtr(NewPtr(Length(s) * SizeOf(Rect)));
  186.       { Please, check for NIL pointers here! }
  187.       err := OutlineMetrics(Length(s),@s[1],numer,denom,yMax,yMin,advA,lsbA,
  188.                             bdsA);
  189.       advance := 0;
  190.       FOR i := 1 TO Length(s) DO { for each character }
  191.          BEGIN
  192.          { Add accumulated advanceWidth and leftSideBearing of current glyph }
  193.          { horizontally to starting point. }
  194.          leftEdge := pt.h + Fix2Long(advance + lsbA^);
  195.          r := bdsA^; { The bounding box rectangle is in TrueType coordinates. }
  196.          temp := r.bottom; { need to flip it "upside down" }
  197.          r.bottom := - r.top;
  198.          r.top := - temp;
  199.          OffsetRect(r,leftEdge,pt.v);
  200.          FrameRect(r); { This is the glyph's bounding box. }
  201.          advance := advance + advA^;
  202.          { "Advance" is Fixed, to avoid accumulation of rounding errors. }
  203.          { Now, bump pointers for next glyph. }
  204.          bdsA := RectPtr(ord4(bdsA) + SizeOf(Rect));
  205.          advA := FixedPtr(ord4(advA) + SizeOf(Fixed));
  206.          lsbA := FixedPtr(ord4(lsbA) + SizeOf(Fixed));
  207.       END;
  208.       DisposPtr(Ptr(advA));
  209.       DisposPtr(Ptr(lsbA));
  210.       DisposPtr(Ptr(bdsA));
  211.    END; { DrawBoxedString }
  212. OutlineMetrics exists because many developers need pixel-precise information on placement and bounding boxes, often on a character-by-character basis.  Unfortunately, there is no similar facility for text drawing with bitmap fonts. Worse, under certain circumstances, italicized or shadowed (or both) bitmap fonts are sometimes poorly clipped, particularly for scaled sizes. Cosmetic workarounds include adding a space character to strings drawn in italic.  You might also draw the text off-screen first (in order to determine the bounding box of the black pixels) and use CopyBits to copy the text onto the screen—but using CopyBits for text is usually bad for printing.
  213. The existing documentation on the FMOutput and global width table structures (Inside Macintosh Volume I, page 227 and Volume IV, page 41) suggests it’s possible to devise a routine for determining a fairly precise text bounding box for bitmap fonts. The procedure below,  BitmapTextBoundingBox, is a first attempt. It assumes that TrueType is unavailable, or that the IsOutline call returned FALSE for the current port settings. While the returned bounding box is not always “tight,” be careful before modifying the algorithm and shrinking the resulting bounding box—bitmap fonts just don’t  contain enough precise information for an exact bounding box, and different bitmap fonts and different sizes may require different adjustments.
  214. PROCEDURE TextBoundingBox(s: Str255; numer,denom: Point; VAR box: Rect);
  215.    CONST
  216.       FMgrOutRec = $998; { FMOutRec starts here in low memory }
  217.       tabFont = 1024;
  218.       { global width table offset for font record handle, see IM IV-41 }
  219.    TYPE
  220.       FontRecPtr = ^FontRec;
  221.    VAR
  222.       hScale,vScale: Fixed;
  223.       err,intWidth,kernAdjust: Integer;
  224.       xy: Point;
  225.       info: FontInfo;  { only for StdTxMeas; we'll use FontMetrics }
  226.       fm: FMetricRec;  { see Inside Macintosh, IV-32 }
  227.       fmOut: FMOutput;
  228.       h: Handle;
  229.    BEGIN
  230.       intWidth := StdTxMeas(ord(s[0]),@s[1],numer,denom,info);
  231.       { calls FMSwapFont and everything - }
  232.       { StdTxMeas returns possibly modified scaling factors numer, denom }
  233.       hScale := FixRatio(numer.h,denom.h); 
  234.       vScale := FixRatio(numer.v,denom.v);
  235.       { These are the scaling factors QuickDraw uses    }
  236.       { in "stretching" the available character bitmaps }
  237.       fmOut := FMOutPtr(FMgrOutRec)^;
  238.       { has been filled by the most recent FMSwapFont,  }
  239.       { implicitly called by StdTxMeas  }
  240.       SetRect(box,0, - info.ascent,intWidth,info.descent);
  241.       { bounding box for unscaled plain text }
  242.       IF (italic IN thePort^.txFace) AND (fmOut.italic <> 0) THEN BEGIN
  243.       { the following is heuristics … }
  244.          box.right := box.right + (info.ascent + info.descent - 1) *
  245.                       fmOut.italic DIV 16;
  246.          FontMetrics(fm);
  247.          HLock(fm.WTabHandle); { We'll point to global WidthTable. }
  248.          h := Handle(LongPtr(ord4(fm.WTabHandle^) + tabFont)^);
  249.          { Be sure it's a handle to a 'NFNT' or 'FONT' ! }
  250.          kernAdjust := FontRecPtr(h^)^.kernMax;
  251.          OffsetRect(box, - kernAdjust,0);
  252.          HUnlock(fm.WTabHandle);
  253.       END;
  254.       IF (bold IN thePort^.txFace) AND (fmOut.bold <> 0) THEN
  255.          box.right := box.right + fmOut.bold - fmOut.extra;
  256.       IF (outline IN thePort^.txFace) THEN InsetRect(box, - 1, - 1);
  257.       IF (shadow IN thePort^.txFace) AND (fmOut.shadow <> 0) THEN BEGIN
  258.          IF fmOut.shadow > 3 THEN fmOut.shadow := 3;
  259.          box.right := box.right + fmOut.shadow;
  260.          box.bottom := box.bottom + fmOut.shadow;
  261.          InsetRect(box, - 1, - 1);
  262.       END;
  263.       { Now scale the box (more or less) as QuickDraw would do. }
  264.       { Note that some of the adjustments are based on trial and error… }
  265.       box.top := FixRound(FixMul(Long2Fix(box.top),vScale));
  266.       box.left := FixRound(FixMul(Long2Fix(box.left),hScale)) - 1;
  267.       box.bottom := FixRound(FixMul(Long2Fix(box.bottom),vScale)) + 1;
  268.       box.right := FixRound(FixMul(Long2Fix(box.right),hScale)) + 1;
  269.       GetPen(xy);
  270.       OffsetRect(box,xy.h,xy.v);
  271.    END;
  272. Conclusion
  273. At the time when the original Font Manager architecture was designed, based on QuickDraw’s hard-coded 72 dpi resolution, nobody could anticipate that some years later, the Macintosh would be used to tackle professional typesetting projects. Several advanced page layout applications managed to work around the “built-in” limitations, at high development costs, and some compatibility and performance problems. In many other cases, however, those limitations caused questions to DTS and unsatisfying compromises. This Note can’t do much more than explain the state of affairs; the real solution to the problems must come from a redesigned foundation. TrueType leads the way and already fulfills many of the requirements; everything else is getting closer and closer.
  274. Further Reference:
  275. •    Inside Macintosh, Volume I, Chapter 7, The Font Manager
  276. •    Inside Macintosh, Volume IV, Chapter 5, The Font Manager
  277. •    Inside Macintosh, Volume V, Chapter 9, The Font Manager
  278. •    Inside Macintosh, Volume VI, Chapter 12, The Font Manager
  279. •    New & Improved Inside Macintosh, Imaging: The Font Manager. Developer CD Series disc, path Developer Essentials: Technical Docs: Inside Macintosh Previewf
  280. •    Macintosh Technical Note #91, Picture Comments—The Real Deal
  281. •    M.IM. FontNames
  282. •    M.TE.FontsAndScripts
  283. •    M.IM.FontFamilies
  284. •    Apple LaserWriter Reference, Chapter 2, Working With Fonts ( Addison-Wesley, 1988)
  285. •    Adobe Technical Note #0091 (PostScript Developer Support Group), Macintosh FOND Resources
  286. PostScript and Adobe are registered trademarks of Adobe Systems Incorporated.
  287. Helvetica and Palatino are registered trademarks of Linotype AG and/or its subsidiaries.
  288. Velocio is not a trademark of the author.
  289. Font Manager Q&As
  290. Text        M.TX.FontMgr.Q&As
  291. Revised by:    Developer Support Center    October 1992
  292. Written by:    Developer Support Center    October 1990
  293. This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
  294. Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
  295. New Q&As and Q&As revised this month are marked with a bar in the side margin.
  296. Chicago Control-Q prints propeller or clover symbol
  297. Written:    7/4/90
  298. Last reviewed:    8/1/92
  299. How do I get the character that represents the clover used for command-key equivalents in documents and in menus?
  300. ___
  301. This key is documented in the Apple Style Guide, which is available on the latest Developer CD Series disc as well as from APDA. One little feature of Key Caps which is not widely known is the Control key (not the Command or Option keys). Pressing the Control key in Chicago shows that Control-Q in Chicago maps to the propeller symbol for which you search. Control-Q generates the character code 17; the standard Macintosh character set (see Inside Macintosh Volume VI, page 12-5) specifies this symbol for it.
  302. Determining Macintosh system font size
  303. Written:    2/11/91
  304. Last reviewed:    8/1/92
  305. How does a program determine the default system font size?
  306. ___
  307. If you want to know the default system font size, use the GetDefFontSize call (Inside Macintosh Volume V, page 314). This call will return the true default system font size. On all Roman systems the sysFontSize low-memory global is always zero by default; this means that it’s actually 12. Don’t ask me why they did this, but it’s true, so you should use the call if you want a painless method of obtaining this information. Try to avoid reading the global directly.
  308. FScaleDisable and Macintosh screen rendering
  309. Written:    6/4/91
  310. Last reviewed:    8/1/92
  311. What is the current interface guideline on font scaling? Should we set FScaleDisable to true or false for screen rendering? I believe the old guideline was to set it to true (thus disabling font scaling) so that if you have a 23 pt screen font you will see 12 pt glyphs with 23 pt widths. We want performance on Apple’s low-end machines, and we don’t want to make this a user preference.
  312. ___
  313. Most applications now set FScaleDisable to false all the time. If you are worried about the speed degradation in your application when running on slower Macintosh systems, you could have your software identify which Mac it is running on using Gestalt, SysEnvirons, etc., and then set FScaleDisable to true only on the slow machines. From the purely interface point of view, “what-you-see-is-what-you-get” is best, if processor speed allows it.
  314. With TrueType there is no issue, since FScaleDisable doesn’t have any effect on an outline font.  
  315. Macintosh double-byte character encoding
  316. Written:    8/5/91
  317. Last reviewed:    8/1/92
  318. When will System 7 and TrueType be able to support a larger character encoding vector than the current 256 characters? Is this something I could do now?
  319. ___
  320. System 7 does not have double-byte character encoding support now. In the future, Apple will use the two-byte UNICODE standard for its operating systems. However, such a change will be huge and therefore will not be available in the near future.
  321. Ever since 6.0.2, KanjiTalk has had double-byte encoding, so you can use the Japanese system at this time. The system which allows you to do this is called shift-JIS (Japanese Input System). The mappings are on the current Developer CD in the Kanji folder.
  322. 'FOND' resource features subject to change
  323. Written:    6/17/91
  324. Last reviewed:    8/1/92
  325. Which 'FOND' features are subject to change, and what parts can I rely on?
  326. ___
  327. 'FOND' features not documented in Inside Macintosh, Macintosh Technical Notes, or develop are subject to change. That’s the official word.
  328. Five font style-mapping table styles
  329. Written:    6/17/91
  330. Last reviewed:    8/1/92
  331. Why is “47” the bounds of the indexes’ array in the StyleTable?
  332. ___
  333. The style-mapping tables, which are used for mapping of a font style to a particular font for printing, have only five possible styles, unlike the six screen styles (underline is omitted, since a laser printer just explicitly draws a line under the string—it doesn’t need a special font for that). You can have any combination of these five styles, EXCEPT that you can’t have “Condense” and “Extend” at the same time (Condensed Extended wouldn’t make a whole lot of sense). Thus you get (combinatorics come back to haunt us) 48 possible unique styles to map to.
  334. X-Ref:
  335. Snippet “StyleMap” on the Developer CD.
  336. LaserWriter Reference, Chapter 2, “Working with Fonts,” (Addison-Wesley; APDA  #M7073, $19.95).
  337. System 7 and modified fonts
  338. Written:    6/21/91
  339. Last reviewed:    8/1/92
  340. We ship modified versions of the Chicago and Geneva fonts and their FONDs in our application’s resource fork. With System 6, when we ask for font 0 or font 3, we get our modified fonts in windows, buttons, menus and dialogs, but not with System 7. Is there a new way to tell System 7 to use my version of Chicago 12 to display all system related stuff?
  341. ___
  342. What’s happened is that the system software is being much more strict about whose “Chicago” it uses for menus and dialogs. The Menu and Control Managers now only look at the system file for the Chicago they use.
  343. There are a couple of ways to get around this: First, you can try patching DrawString right before calling MenuSelect in your program. The patch would select your Chicago and then jump to the standard DrawString. After MenuSelect, remove the patch. The disadvantage of this method is that, if a future system software release doesn’t use DrawString for drawing menus, the patch would cease to have any effect.
  344. A better solution is to write your own menu and control definition code—in other words, your own custom MDEF and CDEFs. The way you typically do this is to get a copy of the standard Macintosh system’s MDEF or CDEF, and alter it to your specifications. In your case, this would be merely selecting your font instead of the system font. Name your font something other than Chicago and just select that font by name in the menu or control’s draw routine. The Control and Menu Manager chapters in Inside Macintosh Volume I have more information on writing custom definitions. There is only one problem with this right now: While the System 6 MDEF and CDEF are available on AppleLink, the System 7 versions are not available yet, although they will be soon.
  345. A note on the use of Chicago in your application: As the June 1991 edition of the Macintosh Technical Note “Font Family Numbers” mentions, fonts are copyrighted material. Apple owns the Chicago font and typeface, so be sure you check into licensing issues before releasing any version, altered or unaltered, with your application.
  346. Spanish typographic measurements
  347. Written:    12/10/91
  348. Last reviewed:    8/1/92
  349. What typographical measurement issues must be considered for Spanish systems? Do the Spanish specify type in ciceros and didots instead of points?
  350. ___
  351. If typesetting is done in Spain with computers, U.S. standards generally are used. It is only when typesetting is done the old-fashioned way that you’ll see different measurements.
  352. Paper sizes are different. In Spain DIN-44 (210 x 297), DIN-A3 (420 x 297) and “folio” (215 x 315) are used. As always, you’ll be working with 72 dpi for the screen (and any time you use QuickDraw) but something different on paper, so you’ll need to use PrGeneral and image the stuff yourself to a resolution that allows you control over your imaging for printing. This is detailed in the article, “Meet PrGeneral, the Trap That Makes the Most of the Printing Manager,” in issue #3 of develop.
  353. Here are the measurements used in Spain:
  354. • Decimal point (Didot) (0.3759 mm)
  355. • Millimeter
  356. • Cicero (12 decimal points)
  357. • Centimeter
  358. • Inches
  359. SetOutlinePreferred = TRUE or not?
  360. Written:    12/2/91
  361. Last reviewed:    8/1/92
  362. My application calls SetOutlinePreferred so outline fonts are used if both bitmapped and TrueType fonts are in the system. It was reported to me, however, that some international TrueType fonts in particular look really bad at small point sizes on the screen. Should I avoid calling this function?
  363. ___
  364. SetOutlinePreferred is best used as a user-selectable option. Along the same lines, you might want to include the SetPreserveGlyph call (Inside Macintosh Volume VI, page 12-21), again, as a user-selectable option.
  365. Currently, as you know, the default for outlinePreferred is FALSE; this is for compatibility reasons (existing documents don’t get reflowed if the bitmap fonts are still around) and for esthetic and performance reasons (users are free to maintain bitmap fonts in the smaller point sizes if the TrueType version is not satisfying for small sizes, or too slow). On the other hand, as soon as a bitmap font is *un*available for a requested point size, and an outline font is present, the outline font is used even with outlinePreferred = FALSE. Setting outlinePreferred = TRUE makes a difference only for point sizes where a bitmap font strike is present along with a 'sfnt' in the same family/style.
  366. TrueType fonts might be preferable even for small point sizes if linearly scaled character widths are more important than screen rendering: If the main purpose of a program is preprint processing for a high-resolution output device, then outlinePreferred = TRUE may give better line layout results on the printer, at the price of “not so great” type rendering on a 72 dpi screen. (An example for the conflict between linearly scaling TrueType and non-linearly scaled bitmap fonts is Helvetica: StringWidth('Lilli') returns 19 for the 12-point bitmap font, and 15 for the 13-point  size from TrueType!)
  367. All this boils down to the recommendation stated initially: The user should be given the flexibility to decide whether to use the existing bitmaps (using TrueType only for bigger point sizes and high-resolution printers), or to go with TrueType even if the result on the screen is not optimal. (By the way, it’s likely that TrueType development will substantially reduce this conflict in the future.)
  368. FontRec fontType field and determining monospaced fonts
  369. Written:    1/13/92
  370. Last reviewed:    8/1/92
  371. How can I create a menu that contains only fixed width fonts? The FontRec record’s fontType field doesn’t correctly tell me if the font is fixed width as Inside Macintosh Volume V says it should. All system fonts appear to have the same fontType regardless of whether they are fixed or proportional. Currently I test if the width of the characters “m” and “i” are equal and if they are, I consider the font to be fixed width. Is there an easier (and faster!) way?
  372. ___
  373. The Font Manager documentation is not explicit enough about the fact that bit 13 (0x2000) of the fontType field is basically useless. Neither does the Font Manager check the setting of this bit, nor does QuickDraw (or any printer driver). As you observed, monospaced fonts like Monaco or Courier don’t have the bit set; so the meaning of this bit is just perverted to nonsense—sorry! In addition, the fontType field only is available for 'FONT's and 'NFNT's; it does not exist in 'sfnt's, and you would have to check separately for the resource type of the font.
  374. Your idea of comparing the widths of “m” and “i” (or any other characters which are extremely unlikely to have the same widths in a proportionally spaced font) is indeed the only reasonable way of figuring out if a font is monospaced.
  375. Getting global width table for a font specification
  376. Written:    4/22/92
  377. Last reviewed:    8/1/92
  378. What’s the fastest way to get the width table for a given font? FontMetrics is too slow, especially in color. Is there any other call that will get the global width table set up correctly? That is all that we need from the call to FontMetrics.
  379. ___
  380. FontMetrics does not have much overhead in setting up the width table. It does a dummy DrawChar(' '); this is very rapidly transformed into a call to StdText, and StdText immediately calls StdTxMeas. The first thing StdTxMeas does is to set up the input parameters for a FMSwapFont call and call it. FMSwapFont is the heart of the Font Manager, and does all the work. It comes back with the FMOutput record, the font strike, and the width table. From there, FontMetrics derives the values it needs to bring back.
  381. You probably wouldn’t save much more than 1/1000th of a second if, instead of calling FontMetrics, you called FMSwapFont explicitly yourself—our only alternative suggestion.
  382. The Font Manager does quite a lot of caching (up to 12 width tables), and managing the cache takes some cycles, too. If there is nothing in the cache corresponding to the font request, the cache makes the call even slower than it would be without cache.
  383. The next source of overhead is the Resource Manager. Looking for a specific font involves going through the whole resource chain first for the FOND (if none is found, the search restarts for a FONT), and then, based on the FOND’s font association table, for a NFNT or 'sfnt'. If no NFNT is found, the search restarts for a FONT, always through the whole resource chain. For a huge resource fork like in the System file (and, maybe, also in your application), the time spent in the Resource Manager is not negligable—in particular, if you have add-ons in your system (such as INITs or 'cdev's) that patch out Resource Manager calls, maybe several times, and usually slow it down considerably!
  384. Even in case this hurdle is overcome swiftly (after all, the Resource Manager has its own caching scheme for optimization), the next step necessarily takes some time, and, as you have observed, especially on a color system: It consists of actually providing the bitmap for the font strike. If the screen depth is >1, this involves creating “synthetic” fonts for the correct screen depth, to optimize text drawing. Also, if the font is an outline font, the first time a font strike has to be rasterized is quite costly in terms of machine cycles.
  385. Finally, the width table can be created; and, because of the scaling factors involved, this requires 256 times some arithmetic which is known never to be fast enough.
  386. All this certainly gives us an understanding for the time it takes FMSwapFont (FontMetrics) to get the job done, but it does not solve your problem.
  387. Depending on how predictable the usage of fonts and width tables in your application is, you might consider building kind of a database of width tables beforehand, or along the way, and use this information directly from within your application. There is no shortcut at all through the Resource Manager to get at the font resources, and there is no shortcut within FMSwapFont, like not building the font bitmaps. (To the best of my knowledge, the needbits field in the FMInput record does *not* have this effect.) The only obvious way to get width tables faster is to keep them around, and to extend manually the capacity of the Font Manager’s cache of width tables.
  388. SetFractEnable and recalculating width tables
  389. Written:    5/5/92
  390. Last reviewed:    8/1/92
  391. Calling SetFractEnable seems to force the width tables to be recalculated regardless of the setting of the low-memory global FractEnable. We’re calling this routine at a central entry point for any document, as it’s a document by document attribute. We then unconditionally call SetFractEnable(false) on exit back to the event loop, to be nice to other applications. Calling SetFractEnable(false), seems to trigger the recalculation even though FractEnable is false. What’s the best way to get around this?
  392. ___
  393. Your observation is correct. The SetFractEnable call stuffs the boolean parameter (as a single byte) into the low-memory global $BF4 and indiscriminately invalidates the cached width table by setting $B4C (LastSpExtra) to -1 (LongWord = Fixed). Obviously, it was not anticipated that SetFractEnable could be called quite regularly with a parameter that often does not change the previous setting. (By the way, the same observation applies to the SetFScaleDisable call).
  394. In your case, you may want to replace the SetFractEnable call by your own test of the boolean (8-bit) in $BF4 (FractEnable), and call SetFractEnable only if the parameter passed is different from the value stored in $BF4. Note that Inside Macintosh Volume IV (page 32) explicitly allows you to hack the $BF4 location directly, so it’s unlikely there are any future compatibility problems if you go your own way around the original SetFractEnable. The only additional information you need is what’s mentioned above: The Font Manager always checks $B4C (LastSpExtra) for -1 before doing anything with the global width table; if it finds ($B4C) = LongInt(-1), it painfully rebuilds the width table.
  395. Another comment: You do not need to think of other applications when resetting FractEnable; in a context switch to another application, all low-memory globals are swapped anyway. Still, the above optimization of SetFractEnable probably is useful even when you don’t call it any more systematically on exit to the event loop.
  396. Corrupted Macintosh font or font suitcase criteria
  397. Written:    6/19/92
  398. Last reviewed:    9/15/92
  399. I would like to be able to detect whether a font suitcase is corrupted when it is opened and whether any of the fonts in it are corrupted before any of the fonts are used. I know that the Finder is able to do this, and I was wondering if Apple gives out this information. My program will only run under System 7.0 if that helps. Any information that you can give me would be greatly appreciated.
  400. ___
  401. The Finder and the type architecture are living things; the definition of what is and is not a damaged suitcase can change from release to release of system software. However, any of the following conditions makes System 7.0 report the suitcase as “damaged”:
  402. • More than eight FONDs reference the same font.
  403. • A new stand-alone object can’t be created for a font icon. The usual cause of this is that two FONDs have the same name for the first 31 characters, and the Finder thinks there’s already an icon in that window with the same name. (Two icons in the same directory with the same name is a sign of damage.)
  404. • There must be at least one font association table entry, and the table can’t go past the logical end of the resource.
  405. • The first resource name in the map must not be zero-length (which is a test for some older third-party corrupted suitcases).
  406. • The FOND must have a name.
  407. • The FOND must have a valid character range—the first character has to be less than the last character—unless it is a "dummy" FOND (created on the fly for old standalone FONTs; in this case, last character = 0).
  408. • All the font association table entries must be in ascending point size order.
  409. • No two font association table entries may reference exactly the same point size and style.
  410. • The offsets to the width table, kerning table and style mapping table must be valid or zero.
  411. • The font ID must not be zero unless it’s actually the system font.
  412. We can’t promise this is every reason the Finder would report a suitcase as damaged (especially given the second step), but this is most of them.
  413. Fonts and the Script Manager
  414. Text        M.TE.FontsAndScripts
  415. Written by:    John Harvey & Peter Edberg    June 1989
  416. This Technical Note describes how the Script Manager uses the font family ID to determine a script code.
  417. The traps _FontScript, _IntlScript, and _Font2Script all use a font family ID to determine the script interface system code that they return.  This Note describes the process, the way the Script Manager renumbers the Chicago font for non-Roman systems, and the equation for calculating Script IDs from font family IDs.
  418. On a Roman system the Chicago 'FOND' is numbered zero, but this causes no confusion since Chicago is also the system font.  Non-Roman systems must renumber Chicago so that it will not interfere with the mapping of 'FOND' ID = 0 to the correct system 'FOND'.  Typically Chicago is renumbered to 16383.
  419. In Inside Macintosh, Volume V-293, The Script Manager, the descriptions of _FontScript, _IntlScript, and _Font2Script state that the current font identification number (e.g., 'FOND' ID) is used to calculate the correct script code.   The equation for calculating script codes from 'FOND' IDs is as follows:
  420. script =((FONDid - $4000) DIV 512) + 1
  421. For a specific example, consider the Kyoto font which is one of the fonts included in KanjiTalk.  Its 'FOND' ID is 16385.  Plugging that value into the equation above, we get: script = ((16385-16384) DIV 512) +1.  Which results in a value of one, the script code for the Kanji script system.
  422. Note that this means that script systems other than Roman can only have 512 separate font families.  Furthermore, Roman font families (FOND) must not have an ID greater than 16383, and 'FOND' ID 16383 is reserved for Chicago on non-Roman systems.
  423. So How Do They Work?
  424. _FontScript, _IntlScript, and _Font2Script begin by setting two Script Manager globals, Forced and Default to false.  Then the two special font family ('FOND') numbers zero and one are mapped to the System and Application font.
  425. Next the 'FOND' ID is tested to see if it is an international font.  _FontScript and _IntlScript simply take the value out of the txFont field of the current grafPort.  _Font2Script uses the value passed to it.  The test is simply:
  426. IF FONDid < $4000  {16384}
  427.     script is Roman so return 0
  428. ELSE
  429.     script is international so calculate script id using equation described above
  430. Once the script code has been determined, the routine looks at the the Script Manager globals FontForce and IntlForce.
  431. If the currently installed script is Roman and fontForce is true, or if intlForce is true and the routine called was _IntlScript, then the value returned will be the current system script.  If the installed script is not Roman; the script code calculated will be returned when the routine called was _IntlScript, intlForce is true, and the script code does not equal the system script.
  432. Once the script code to be returned as been calculated, a final check is made to be sure that the script is installed and enabled.  If it is not; Roman is returned, and Forced is set to false and Default is set to true.
  433. What’s This Forced Stuff?
  434. Two Script Manager globals, fontForce and intlForce, are flags that support compatibility.  Turning fontForce on will cause Roman fonts to be interpreted as belonging to the system script.  This provides compatibility for applications that hard-code font numbers.
  435. For example, the Arabic script interface system provides a cdev which lets a user turn fontForce on.  When a user does this, any Roman fonts will be mapped to an Arabic font.  Note this is only a partially effective measure since the user still does not have complete control over fonts.
  436. It should also be noted that if a user sets fontForce on via the cdev, values returned for fonts with family IDs in the range $0002 to $3FFF (Roman 'FOND' ID range) may vary.  This is not a good feature for applications that allow mixed text.  To avoid this problem, an application can turn the fontForce flag off before calling _Font2Script or _FontScript.  The flag value should be saved before turning it off, and restored later.
  437. The intlForce flag determines how the call IUGetIntl behaves.  If this flag is on, IUGetIntl will always return the international resources ('itlx' where x is 0-2) corresponding to the system script.  When intlForce is off, the font in the current port will be used to determine which international resources will be returned.  This flag lets an application control what  date formats, sorting routines, etc. will be used.
  438. For that reason, before calling any of the international utility routines or using the binary to decimal routines, an application should verify that thePort and thePort^.txFont are set correctly, or that intlForce is set properly.
  439. Let’s Look at a Picture
  440. The flowchart in Figure 1 illustrates the operation of _FontScript, _IntlScript, and _Font2Script, and how they are affected by the global flags fontForce and intlForce.
  441. Figure 1–Operation Flowchart
  442. Further Reference:
  443. •    Inside Macintosh, Volume I-493, The International Utilities Package
  444. •    Inside Macintosh, Volume V-293, The Script Manager
  445. •    Inside Macintosh, Volume V-287, The International Utilities Package
  446. International Resource Q&As
  447. Text        M.TX.IntlRsrc.Q&As
  448. Revised by:    Developer Support Center    October 1992
  449. Written by:    Developer Support Center    October 1990
  450. This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
  451. Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
  452. New Q&As and Q&As revised this month are marked with a bar in the side margin.
  453. Determining the language being used to enter text
  454. Written:    11/20/90
  455. Last reviewed:    8/1/92
  456. Is there a way to tell what language is being used on the Macintosh? I know how to find the script and other international items, but the language being spoken would be a very useful thing to know.
  457. ___
  458. It depends on what you mean by “language.” It’s impossible to determine what language the user is typing in without doing a high-level analysis of what is being typed, as you probably know.
  459. One way that’s been suggested in the past is to check on the current KCHR by calling GetScript with an smScriptKeys verb. This returns the resource ID of the currently active KCHR. All international systems come with a U.S. KCHR and possibly others, such as the Romaji and Kana KCHRs in the Japanese systems and the alternative Roman KCHRs in the various German and French systems. The thought was that the user will most likely choose the U.S. KCHR to type in English, and choose the French KCHR to type in French. One problem with this is that it isn’t necessarily true. You can type English with the French KCHR and you can type French with the U.S. KCHR, and many people do. A much larger problem is that the KCHR IDs aren’t standardized within a script system range. Because Apple defines a range of resource IDs for each script system for the international resources, you can tell what script system a KCHR is for, and you can even match up the KCHR ID with the standard KCHR IDs that Apple defines, but there’s nothing wrong with someone creating their own KCHR and giving it any ID they want, as long as it’s in the proper range for the script system they’ve written it for. If that’s the currently active KCHR, its resource ID tells you what script system it’s for, but it won’t tell you anything about what language it was intended for. For this reason, this method is frowned upon now.
  460. In fact, there really is no reliable way of knowing the language that’s being used. The best you can do currently is to find out what the system is localized for. This is done by grabbing the vers resource ID 1 from the System file. In this resource is what was called the country code (the term “country code” is obsolete, in favor of “region code”) which indicates what region the system is localized for. These region codes are defined in Packages.p in MPW, and have names like verUS and verFrance and the like.
  461. There’s another way that you might want to consider. One of the GetScript verbs is smScriptLang. This returns the language code of the specified script system for the current system. If you pass smRoman as the script code to GetScript, it’ll return langFrench on a French system, langGerman on a German system, langEnglish on a U.S. or U.K. or Australian system, and so forth. If you pass smJapanese as the script code to GetScript, it’ll return langJapanese. Interestingly, if you pass smRoman as the script code to GetScript when a Japanese script system is running, it’ll return langEnglish. All non-Roman script systems return langEnglish if you pass smRoman as the script code to GetScript. The language constants are in Language.p in MPW. You’ll probably what to combine this GetScript call with a call to GetEnvirons to find out what the currently active script is. It might look something like this:
  462. (* Get the currently-active keyboard script *)
  463. keyboardScript := GetEnvirons (smKeyScript);
  464. (* Now get the language that the keyboard script corresponds to *)
  465. languageCode := GetScript (keyboardScript, smScriptLang);
  466. In summary, there’s no system support for retrieving the language that the user is typing, nor is there any reliable support for retrieving the language related to any KCHR. But, you can find the region code of the active system, and you can find the language associated with the active script. Hopefully, that’s enough information to be useful to you.
  467. RelString & EqualString vs International Utilities
  468. Written:    1/25/91
  469. Last reviewed:    8/1/92
  470. What is the difference between RelString and the EqualString? What does DTS suggest its Macintosh developers use when sorting? Or do you suggest having an option for the international sort?
  471. ___
  472. RelString and EqualString are mainly intended for the File Manager. The File Manager uses them for quick-and-dirty string comparison so that it knows how to return files ordered alphabetically when you use an indexed File Manager routines and so that it can detect file name collisions. Beyond that, RelString and EqualString aren’t localizable and they’re not extensible.
  473. The International Utilities string comparison routines are localizable and extensible. They use information in the active 'itl2' resource to determine how the characters are sorted. Most localized systems come with their own 'itl2' resource, and so string comparisons are done correctly for the region that the system is localized for. RelString and EqualString stay the same for all these regions, and so you’ll probably find some cases in which strings are compared incorrectly by these routines.
  474. One important place where RelString and EqualString don’t work very well is with the new characters in the extended Macintosh character set. When the LaserWriter was introduced, the LaserWriter fonts used the extended Macintosh character set which added many new characters, including several new upper-case characters with diacriticals. In system software version 6.0.4, the International Utilities were updated to take advantage of these new characters. For example, the upper case “E” with a grave accent first appeared in the extended Macintosh character set. With 6.0.4, the lower and upper case “E” with a grave accent were considered to be equal in primary ordering, and unequal in secondary ordering, which is correct. But RelString and EqualString, even today, still think in the old Macintosh character set, so they think that lower and upper case “E” with a grave accent have nothing to do with each other, and that’s not right.
  475. Because the RelString and EqualString algorithms are more crude than the string comparison routines in the International Utilities, RelString and EqualString should win races with the International Utilities string comparison routines hands down. The File Manager uses them partly for this reason, and partly because RelString and EqualString don’t need access to the 'itl2' resource, which is usually pretty big. Normally, File Manager sorting isn’t critical anyway because it’s either irrelevant, or it can easily be cleaned up by using the International Utilities string comparison routines. The Standard File package, for example, uses the International Utilities string comparison routines to order file and folder names in its list so that the list is ordered correctly regardless of the system it’s running on.
  476. X-Ref:
  477. Inside Macintosh Volume VI, page 14-82, “The 'itlm' Resource”
  478. Macintosh PRAM’s MachineLocation dlsDelta field
  479. Written:    1/25/91
  480. Last reviewed:    8/1/92
  481. How is the dlsDelta field in PRAM’s time zone MachineLocation record used and set?
  482. ___
  483. Currently, the dlsDelta field is not being used by Macintosh system software, nor is its meaning defined. There are plans to use it in the future, so it’s important that you preserve its current value if you ever use WriteLocation to set the value of gmtDelta. See the description of the WriteLocation routine in “WorldWide Development: Guide to System Software,” available on the latest developer CD and from APDA (#M7047/A), for details on getting and setting gmtDelta while leaving dlsDelta intact. In short, the code looks like this:
  484.     VAR
  485.         myLocation:     Location;
  486.         myGMTDelta:     LongInt;
  487.         tempSignedByte: SignedByte;
  488.     :
  489.     tempSignedByte := myLocation.dlsDelta;
  490.     myLocation.gmtDelta := myGMTDelta;
  491.     myLocation.dlsDelta := tempSignedByte;
  492. Why 1904 is Macintosh Time base
  493. Written:    9/6/91
  494. Last reviewed:    8/1/92
  495. The global variable Time contains the number of seconds since midnight, Jan. 1, 1904. Why was the year 1904 chosen ?
  496. ___
  497. The ability to go back in time is one consideration. You would not want to start the clock from, say, 1984. You also want to go ahead in time a good amount, of course. So, the clock start date needs to put our current date somewhere in the middle of the clock’s range.
  498. So what is the clock’s range? Since the clock chip has a four byte counter which is incremented each second, they had 4,294,967,295 seconds to work with, or approximately 136 years. This would make the Macintosh clock run out in 1904+136 = 2040. The maximum value, $FFFFFFFF, corresponds to 6:28:15 a.m., February 6, 2040.
  499. Given the possible range of years/leap years/nonleap years (every fourth year, but not if at the end of a century, except at the end of every fourth century, which is a leap year) and the date when the clock will run out (2040) - the “leap year code” in the Macintosh only has to deal with the rule “every fourth year is a leap year” because none of the possible Macintosh dates violate that rule! Remember, 2000 is evenly divisible by 400, so it IS a leap year. 1900 is not. If they started at 1900, they would have to use a different algorithm that accounts for “non-leap year” leap years. Some other clocks start on 1901.
  500. Why did they start on 12:00:00, January 1, 1904? Well, it probably has to do with 1904 being the first leap year after a “non-leap year” leap year (1900). So, the year was chosen for mechanical (4 byte limit on number of seconds) and pragmatic (you only want to use one algorithm to figure out the date et al) considerations.
  501. So, back to the future...
  502. X-Ref:
  503. Chapter 4, “Worldwide Guide to System Software”
  504. System 7 and 'itl1' resources
  505. Written:    9/16/91
  506. Last reviewed:    8/1/92
  507. System 7 doesn’t recognize some of my 'itl1' resource changes, such as date abbreviation length, that are recognized by System 6.
  508. ___
  509. The field that you refer to is not doing what you want because System 7 introduced an expanded 'itl1' resource, with several new fields, including arrays that contain the proper abbreviations of all the months and days. If you look in Inside Macintosh Volume VI on pages 14-87 thru 14-89 you’ll find a description of this new resource as well as the rez definition of it. Note the two new arrays, abbrevDays and abbrevMonths. If you were to modify these additional fields, you’d see the date in the finder windows change. (In fact, the abbrev length field does not seem to be used if these new fields are present.)
  510. 'itl0' resource time1Suff…time8Suff field interpretation
  511. Written:    11/4/91
  512. Last reviewed:    8/1/92
  513. How are the 'itl0' resource time1Suff, time2Suff, … to be interpreted? On the German system, these bytes seem to contain “ Uhr Uhr.” The correct 24-hour time suffix should be a single “ Uhr.” How do we know how many bytes of this 8-character entity are significant? Similar question for the mornStr and eveStr: are all 4 characters of each of these significant?
  514. ___
  515. The time1Suff…time8Suff fields in the 'itl0' resource of all localized systems divide those fields into two sections. The first four bytes (time1Suff through time4Suff) are used from 12:00 midnight through one second before noon, and the last four bytes (time5Suff through time8Suff) are used from 12:00 noon through one second before midnight. This is to take into account any system that has hours from 00:00:00 through 23:59:59, but has different time trailers for the morning and evening hours. I don’t know of any that work this way offhand, though. The German standard is just to append “Uhr” onto the time, morning or evening, and it’s separated from the time by one space. Any unused bytes just contain zero. For example, if the German time suffix was “Uh”, then the time suffix fields would contain a space, “U”, “h”, zero, space, “U”, “h”, and zero. If there’s no time suffix, then all eight bytes are zero.
  516. The morning string and evening strings are done in a similar way. Each one holds a maximum of four bytes, and any unused bytes are filled with zeros.
  517. By the way, you’ll find that a lot of time suffixes are filled in with something even though the flags say that time suffixes aren’t used. This is just localization garbage, which probably will be cleaned up someday.
  518. International Canceling
  519. Text        M.TE.InternationalCancel
  520. Written by:    John Harvey    February 1990
  521. This Technical Note describes potential problems canceling operations with the Command-period key sequence and international keyboards.
  522. Where Did That Key Go?
  523. Canceling an operation, from printing to compiling, has always been done with the key sequence Command-period.  The problem with this is that on some international systems, one needs to hold the Shift key down to produce a period.  Many keyboard mappings, including that of the U.S., ignore the Shift key when the Command key is down.  In other words, on a system where a period (.) is a shifted character (e.g., Italian) pressing Command-Shift-KeyThatMakesAPeriod does not generate the ASCII code for a period.  Instead, the keyboard mapping software generates the ASCII code for the unshifted character.  If an application is looking for Command-period to cancel some time intensive operation, and an international user types the shifted key sequence that normally produces a period along with the Command key, the application is going to miss that request unless it takes special precautions.
  524. A Bit Confusing (to me at least)
  525. The solution to this potential international disaster is to strip the Command key out of the modifiers, and then run the key code back through the keyboard mapping software.  The trap _KeyTrans makes this procedure very easy.  _KeyTrans takes as parameters a pointer to a 'KCHR' resource (see M.TB.KeyMapping), a word which contains the keycode and the modifier bits, and a word which serves as a state variable.
  526. One note on the result returned by _KeyTrans.  Inside Macintosh, Volume V-195, The Toolbox Event Manager, states, “ASCII 1 is the ASCII value of the first character generated by the key code parameter.”  This statement is followed by an illustration (Figure 7 on page V-195) which shows ASCII 1 as the low byte of the high word in the long word result.  Although this statement and the accompanying illustration are correct, they have mislead a number of people (me for one).
  527. It is dangerous to expect the character code in one particular word of the long word result.  In fact, the architecture of the _KeyTrans trap does not specify which word contains the character code in which you might be interested.  This is because the _KeyTrans trap’s primary purpose is to create a package that can be used to build a key-down event, and the Toolbox Event Manager just doesn’t care about particular keys.  In fact, it is possible to get a result from _KeyTrans that contains character codes in both words.  This is how dead keys are handled.
  528. But how does one handle a particular character, specifically a period?  The strategy adopted in the sample function in this Note is to check both words of the result.  If a period exists in either word and the Command key is down, it is counted as a Command-period key sequence.
  529. Now that everything is straight about parameters and results, it’s time to look at some sample code.  The code fragment which follows ensures that you get that period regardless of the state of the modifier keys.
  530. MPW Pascal
  531. CONST
  532.   kMaskModifier = $FE00; {need to strip command key from Modifiers}
  533.   kMaskVirtualKey = $0000FF00; {get virtual key from event message}
  534.   kMaskASCII1 = $00FF0000;
  535.   kMaskASCII2= $000000FF; {get key from KeyTrans return}
  536.   kKeyUpMask  = $0080;
  537.   kPeriod = ORD('.');
  538. TYPE
  539.   EventPtr = ^EventRecord;
  540. FUNCTION CmdPeriod(theEvent: EventPtr): Boolean;
  541. VAR
  542.   keyCode     : Integer;
  543.   virtualKey,
  544.   keyInfo,
  545.   lowChar,
  546.   highChar,
  547.   state,
  548.   keyCId      : Longint;
  549.   hKCHR       : Handle;
  550. BEGIN
  551.   CmdPeriod  := FALSE;
  552.   IF ( theEvent^.what = keyDown ) | ( theEvent^.what = autoKey ) THEN BEGIN
  553.     {see if the command key is down.  If it is, get the ASCII }
  554.     IF  BAND(theEvent^.modifiers,cmdKey) <> 0  THEN BEGIN
  555.       virtualKey := BAND(theEvent^.message,kMaskVirtualKey) DIV 256;
  556.     {strip the virtual key by ANDing the modifiers with our mask}
  557.       keyCode := BAND(theEvent^.modifiers,kMaskModifier);
  558.       keyCode := BOR(keyCode,kKeyUpMask);  {let KeyTrans think it was a keyup event, this
  559.                                             will keep special dead key processing from 
  560.                                             occurring }
  561.     {Finally OR in the virtualKey}
  562.       keyCode := BOR(keyCode,virtualKey);
  563.       state := 0;
  564.       keyCId := GetScript( GetEnvirons(smKeyScript), smScriptKeys);
  565.       {read the appropriate KCHR resource }
  566.       hKCHR := GetResource('KCHR',keyCId);
  567.       IF hKCHR <> NIL THEN BEGIN
  568.         { we don't need to lock the resource since KeyTrans will not move memory }
  569.         keyInfo := KeyTrans(hKCHR^,keyCode,state);
  570.         ReleaseResource(hKCHR);
  571.       END
  572.       ELSE
  573.         {if we can't get the KCHR for some reason we set keyInfo to the message field.  This 
  574.          ensures that we still get the Cancel operation on systems where '.' isn't shifted.}
  575.         keyInfo := theEvent^.message;
  576.       LowChar := BAND(keyInfo,kMaskASCII2);
  577.       HighChar := BSR(BAND(keyInfo,kMaskASCII1),16);
  578.       IF ( LowChar = kPeriod ) | (HighChar = kPeriod) THEN 
  579.            CmdPeriod := TRUE;
  580.     END;
  581.   END;
  582. END;
  583. MPW C
  584. #define kMaskModifiers  0xFE00 // we need the modifiers without the command key for KeyTrans
  585. #define kMaskVirtualKey 0x0000FF00 //get virtual key from event message for KeyTrans
  586. #define kUpKeyMask      0x0080
  587. #define kShiftWord      8 //we shift the virtual key to mask it into the keyCode for KeyTrans
  588. #define kMaskASCII1     0x00FF0000 // get the key out of the ASCII1 byte
  589. #define kMaskASCII2     0x000000FF  //get the key out of the ASCII2 byte
  590. #define kPeriod         0x2E // ascii for a period
  591. Boolean CmdPeriod( EventRecord *theEvent )
  592. {
  593.   Boolean  fTimeToQuit;
  594.   short    keyCode;
  595.   long     virtualKey, keyInfo, lowChar, highChar, state, keyCId;
  596.   Handle   hKCHR;
  597.   fTimeToQuit = false;
  598.   if (((*theEvent).what == keyDown) || ((*theEvent).what == autoKey)) {
  599.   // see if the command key is down.  If it is, find out the ASCII
  600.   // equivalent for the accompanying key.
  601.   if ((*theEvent).modifiers & cmdKey ) {
  602.     virtualKey = ((*theEvent).message & kMaskVirtualKey) >> kShiftWord;
  603.     // And out the command key and Or in the virtualKey
  604.     keyCode    = ((*theEvent).modifiers & kMaskModifiers)  |  virtualKey;
  605.     state      = 0;
  606.     keyCId     = GetScript( GetEnvirons(smKeyScript), smScriptKeys );
  607.     hKCHR      = GetResource( 'KCHR', keyCId );
  608.     if (hKCHR != nil) {
  609.       /* Don't bother locking since KeyTrans will never move memory */
  610.       keyInfo = KeyTrans(*hKCHR, keyCode, &state);
  611.       ReleaseResource( hKCHR );
  612.     }
  613.     else
  614.      keyInfo = (*theEvent).message;
  615.     lowChar =  keyInfo &  kMaskASCII2;
  616.     highChar = (keyInfo & kMaskASCII1) >> 16;
  617.     if (lowChar == kPeriod || highChar == kPeriod)
  618.       fTimeToQuit = true;
  619.   }  // end the command key is down
  620. }  // end key down event
  621. return( fTimeToQuit );
  622. }
  623. What About That Resource
  624. The astute observer may have noticed that the code example requires that you read a resource.  Although this certainly isn’t that big of a deal, it is always nice when you can cut down on disk accesses.  In System 7.0 a verb is added that can be used to get _GetEnvirons to return a pointer to the current 'KCHR'.  The verb is defined and used as follows:
  625. Pascal
  626. CONST
  627.     smKCHRCache =  38;
  628.     KCHRPtr := GetEnvirons(smKCHRCache);
  629. C
  630. #define smKCHRCache 38
  631.     KCHRPtr = GetEnvirons(smKCHRCache);
  632. Unfortunately, in system software prior to 7.0, you must use _GetResource as demonstrated above to obtain the current 'KCHR' resource.  However, since _GetEnvirons always returns zero when passed a verb it does not recognize, you can build System 7.0 compatibility into your application without having to check which system software is running.  To do this, you could modify the routines as follows:
  633. Pascal
  634. CONST {define our own constant until System 7.0 headers ship.  At that point, if you
  635.        have not shipped, you can put in the real constant}
  636.     NewVerb_smKeyCache = 38;
  637. VAR
  638.     KCHRPtr : Ptr;
  639.     KCHRPtr := Ptr(GetEnvirons(NewVerb_smKeyCache ));
  640.     hKCHR   := NIL;  {set to NIL before starting}
  641.     IF KCHRPtr = NIL THEN BEGIN  {we didn't get the ptr from GetEnvirons}
  642.       keyCId := GetScript(GetEnvirons(smKeyScript), smScriptKeys);
  643.       {read the appropriate KCHR resource }
  644.       hKCHR := GetResource('KCHR',keyCId);
  645.       KCHRPtr := hKCHR^;
  646.     END;
  647.     IF KCHRPtr <> NIL THEN BEGIN
  648.       { we don't need to lock the resource since KeyTrans will not move memory }
  649.       keyInfo := KeyTrans(KCHRPtr,keyCode,state);
  650.       IF hKCHR <> NIL THEN
  651.         ReleaseResource(hKCHR);
  652.     END
  653. C
  654. /* again we define our own constant for now */
  655. #define NewVerb_smKeyCache 38
  656. Ptr KCHRPtr;
  657.     hKCHR = nil;  /* set this to nil before starting */
  658.     KCHRPtr = (Ptr)GetEnvirons(NewVerb_smKeyCache );
  659.     IF ( !KCHRPtr ) {
  660.       keyCId = GetScript( GetEnvirons(smKeyScript), smScriptKeys);
  661.       hKCHR   = GetResource('KCHR',keyCId);
  662.       KCHRPtr = *hKCHR;
  663.     };
  664.     IF (KCHRPtr) {
  665.       keyInfo := KeyTrans(KCHRPtr ,keyCode,state);
  666.       if (hKCHR)
  667.         ReleaseResource(hKCHR);
  668.     }
  669. Further Reference:
  670. •    Inside Macintosh, Volume V, The Script Manager
  671. •    Inside Macintosh, Volume V, The Toolbox Event Manager
  672. •    M.TB.KeyMapping
  673. Changes in International Utilities and Resources
  674. Text        M.TE.IUChanges
  675. Revised by:        March 1988
  676. Written by:    Priscilla Oppenheimer    July 1987
  677. The International Utilities package and the international resources have been changed with System file 4.1 to take advantage of the Script Manager.
  678. INTL vs. itl
  679. In the past, there were two INTL resources in the System file, INTL 0 and INTL 1, which contained international formatting options. Starting with System 4.1, itl0 and itl1 replace INTL 0 and INTL 1. (INTL 0 and INTL 1 are still included with the System file so that applications that do a GetResource for them will still find them. Only these erroneous applications that use GetResource will access these resources now; the System will no longer look at them.) There can now be a set of international resources (itls) for each script that is installed. That is, where once there was one resource type (INTL) with IDs 0 and 1 there are now many different resource types (itl0, itl1, itl2, itlb, itlc, KCHR) with distinct resource IDs for the various countries. The U.S. System file uses resource ID 0 for all itl resources.
  680. If your existing application calls IUGetIntl to get the appropriate international resource, you will have no problems under System 4.1. If, however, you call GetResource on INTL 0 or INTL 1 and then modify them, and expect that the System will use the modified resource, you will no longer work correctly. If your application has been released in the past with a modified System file to include your own INTL 0 and/or INTL 1, you may want to release your application with a modified itl0 and/or itl1.
  681. The International Sorting Routine 
  682. The international sorting routine is used to handle cases where letters are equal in primary ordering but different in secondary ordering (e.g., “ä” and “a”). The routine can also handle cases where one character sorts as if it were two, or two characters would sort as if they were one, or even character reversals.
  683. Prior to System 4.1, the international sorting routine was stored starting with the localRtn field of INTL 1. As of System 4.1, this routine is now stored in itl2. An INTL 2 resource is also included with the international resources, just for consistency (the System never uses it). It is exactly the same as itl2.
  684. Writing your own sorting routine can be dangerous if it is not done correctly. Before attempting to do this, we would highly recommend you check with Apple to determine if we are already doing one for the language of interest. We plan to do many international versions of System file 4.1, and most developers’ needs will be met by these. A new policy at Apple will now make it possible to license foreign versions of the System file from Software Licensing. Contact Software Licensing at (408) 973-4667 for more information about this.
  685. Error in APDA draft of Inside Macintosh Volume V 
  686. There is an error in the APDA draft of the International Utilities Package chapter of Inside Macintosh Volume V. It says that there is a flag in the Script Manager globals that overrides the current font and always uses the INTL 0 and INTL 1 resources. This is not true. INTL 0 and 1 have been replaced by itl0 and itl1, and are not used except by applications that explicitly get them by doing a GetResource. There is a relevant Script Manager flag called IntlForce that is correctly but incompletely explained in the Script Manager chapter. When IntlForce is false, the resources used by the International Utilities are determined by the current script. The script that is in use is determined by which font is in use for the port in use. For example, if you switch to the Kyoto font, then you will be using the Japanese Script Interface System (KanjiTalk). If you do this with IntlForce set to false, then you will use the resources that are associated with the Japanese Script Interface System.
  687. When IntlForce is true, the International Utilities always use the resources that are associated with the system script; this is usually Roman. IntlForce is true by default. Actually, the Script Manager initialization routine reads the itlc resource to determine what the default is, and Apple plans to release the various international System files with this field set to true in the itlc resource. Applications that want to change the value of IntlForce can use the Script Manager call SetEnvirons with the smIntlForce verb. There is a Script Manager call, IntlScript, to find out the current value.
  688. Bug in System 4.1 version of itl1
  689. There is a bug in the itl1 resource in System 4.1. The itl1 resource contains arrays of day and month names, as did the INTL 1 resource. Their formats are:
  690. days ARRAY [1..7] of STRING[15]
  691. months ARRAY[1..12] OF STRING[15]
  692. Every day and month is supposed to be coded as a Pascal string with a maximum of 15 characters, and the actual length in the first byte of the string. In System 4.0 and System 4.1, the contents of each string is always a Pascal string of length 15, with the unused characters set to nulls. In other words, the length byte is set to hex 0F. This will be fixed in a future release of the System file. If it is currently causing your application problems, you can change the lengths with ResEdit, or change them at run time, or use your own itl1 resource and release your application with an installer script. The recommended approach is to wait for a fixed version of the System file from Apple.
  693. Further Reference:
  694. •    The International Utilities
  695. •    The Script Manager
  696. Keyboard Resource Q&As
  697. Text        M.TX.KeybdRes.Q&As
  698. Revised by:    Developer Support Center    October 1992
  699. Written by:    Developer Support Center    October 1990
  700. This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
  701. Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
  702. New Q&As and Q&As revised this month are marked with a bar in the side margin.
  703. ResEdit and Macintosh Portable 'KCAP' resources
  704. Written:    6/17/91
  705. Last reviewed:    1/27/92
  706. I am trying to use the 'KCAP' resource to draw the Macintosh Portable keyboard layout in our application. I used the ResEdit to check 'KCAP' in both System 7 and the Key Layout file, but the Portable keyboard type is not there.
  707. ___
  708. The resource numbers 6 and 7 of 'KCAP' are contained in the ROM of the Portable and some other Macintosh models. Being located in ROM, the resources are not directly viewable with ResEdit. They do, however, exist in the resource chain, so a RGetResource for 'KCAP' number 6 should load and return a pointer to this resource. ROM resources and the resource chain are discussed in the Resource Manager chapters of Inside Macintosh Volumes IV and V.
  709. Using Macintosh KCAP resource to draw a keyboard
  710. Written:    1/10/92
  711. Last reviewed:    4/7/92
  712. How can I use the KCAP resource to draw the keyboard?
  713. ___
  714. KCAP resources describe the key layout of Macintosh keyboards. They are intended for use by the Key Caps desk accessory, but applications can also take advantage of KCAPs for information about key arrangements. The program kcapApp demonstrates use of the KCAP resource and is available in the Snippets collection.
  715. This is the format of the KCAP resource:
  716.   rect, boundary for the keyboard (8 bytes)
  717.   rect, appropriate for an editable line of text (8 bytes)
  718.   integer, number of key shapes to follow (2 bytes)
  719.   
  720.   for each key shape:
  721.     integer, number of points defining this key shape - 1 (2 bytes)
  722.     for each point:
  723.       point, opposite corner of a rect (2 bytes)
  724.     number of keys of this shape - 1 (2 bytes)
  725.     for each key:
  726.       byte, modifier mask (1 byte)
  727.       byte, OR/AND setting for modifier mask (1 bit) plus
  728.         virtual keycode for this key (7 bits)
  729.       integer, vertical offset from previous key (2 bytes)
  730.       integer, horizontal offset from previous key (2 bytes)
  731. The keyboard boundary rect may be offset from the origin. It can be realigned with
  732.     OffsetRect(keybdRect, - keybdRect.left, - keybdRect.top)
  733. Each key shape consists of one or more rectangles. The rectangles are defined by a series of points, with one point specifying each rectangle. The first point is the opposite corner of a rectangle anchored at the starting pen location for the key; the next point is the opposite corner of a rectangle from the last point; and so on. The key shape is the union of the rects defined by the points.
  734. Note that a rectangle’s point may be above or to the left of the previous point. To QuickDraw, this would define an empty rectangle, so the rectangle’s horizontal and/or vertical coordinates may need to be swapped before FrameRect is called to add a rect to the key’s region.
  735. The pen is moved to the top left of the keyboard boundary rect before drawing each group of keys of a given shape. The pen location for each key is given as a horizontal and vertical offset from the pen location for the previous key. The pen location for the first key of each shape is an offset from the top left corner of the keyboard boundary rectangle. The pen does not change location when a key is drawn.
  736. Use KeyTrans to determine the character to be drawn on the key. The KCAP resource provides a 7-bit virtual keycode, plus a mask for the modifiers to be passed to KeyTrans. If the most significant bit of the keycode byte is set, AND the desired modifiers with the modifier mask. If the bit is clear, OR the modifiers with the mask.
  737. The high bit of the virtual keycode byte indicates to KeyTrans the type of the keystroke; before calling KeyTrans, clear the bit for a keydown, or set it for a keyup. The bit should be clear if you’re drawing a keyboard. KeyTrans sets the state appropriately for dead keys only when called for keydowns.
  738. The global KbdType ($21E), a byte, contains the KCAP resource number for the last keyboard used. Under System 6, KCAP resources are kept in the file “Key Layout” in the System folder. Starting with System 7, KCAP resources are in the System file. Alternatively, a machine’s KCAP may be stored in ROM, where it’s available with the GetResource call but cannot be viewed with ResEdit.
  739. For more information on KeyTrans and KCHRs, see Chapter 10 of Inside Macintosh Volume V, pages 14-23 and 14-96 of Inside Macintosh Volume VI, and the Macintosh Technical Note “Key Mapping.” KCAP resources are discussed on pages 14-95, 14-100 and 14-101 of Inside Macintosh Volume VI.
  740. Macintosh Option key: Techniques for ignoring
  741. Written:    10/16/91
  742. Last reviewed:    2/28/92
  743. I would like to use the Macintosh Option key as the Control key for keyboards that lack a Control key, such as for Macintosh Plus keyboards. How can I find the ASCII value that would have been returned if the Option key weren’t pressed, in a way that would be compatible with other keyboards?
  744. ___
  745. There are a couple of clean ways to ignore the Option key. One is to “reprocess” the keyboard event. The fourth byte of the event message is the ASCII code, but the third byte is the virtual key code. The system calls the trap KeyTrans to map the virtual key code to ASCII according to a 'KCHR' resource. You can do the same, and since the high byte of the modifiers are part of the input to KeyTrans, you can strip out the Option key, call KeyTrans on the third byte of the event message, and get back the “true” ASCII keypress. KeyTrans and 'KCHR' resources are documented in Chapter 10 of Inside Macintosh Volume V, Chapter 14 of Inside Macintosh Volume VI (pages 14-23 and 14-96), and the Macintosh Technical Note “Key Mapping.” In Pascal, these steps would look something like:
  746.     keycode := BAND(event.message, keyCodeMask); { get virtual code }
  747.     keycode := BSR(keycode, 8); { move to low byte }
  748.     { now combine with modifiers }
  749.     keycode := BOR(keycode, BAND($FF00, event.modifiers)); 
  750.     keycode := BAND(keycode, $FFFF - optionKey); { strip option }
  751.     newkey := KeyTrans(KCHRHandle^, keyCode, state);
  752. The resource ID of the current KCHR is available as GetScript(GetEnvirons(smKeyScript), smScriptKeys). Alternatively, a pointer to the KCHR data is available under System 7 as GetEnvirons(smKCHRCache), as discussed in the Tech Note “International Canceling.”
  753. This method may work for you, but there is a possible problem: dead keys. Since dead keys are processed before your application gets the event, your application will not see (for example) the first Option-e typed. However, the dead keys are specified in the 'KCHR' resource, so you can create a KCHR (ResEdit 2.1.1 includes a template) to omit dead keys (and, if you choose, option characters) and include it with your application. Call SetScript to get the system to use your 'KCHR' (see the Tech Note “Key Mapping,” IM V-313, and IM VI 14-40).
  754. Another problem is that System 7 ignores a 'KCHR' in the application’s resources, so an application’s 'KCHR' has to be installed in the system. You can install the 'KCHR' with an installer program, or provide a keyboard file users can drag to the System file. (To create a keyboard file, use ResEdit to put the 'KCHR' in the System file, and then drag it out with the System 7 Finder.)
  755. Script Manager’s Pixel2Char Routine
  756. Text        M.TE.Pixel2Char
  757. Revised by:    Mark B. Johnson & Dave McGary    August 1989
  758. Written by:    Sue Bartalo    June 1989
  759. This Technical Note discusses the Pixel2Char routine provided by the Script Manager.
  760. Changes since June 1989:  Clarified information, corrected minor errors, and replaced the illustration.
  761. The leftSide flag in the Pixel2Char routine was inappropriately named, and it should now be called the leadingEdge flag.  The reason for this change is that the value Pixel2Char returns indicates whether a mouse-down occurred on the leading edge of a character, which is not always the left side.  (In Arabic or Hebrew, both of which are right-to-left scripts, the mouse-down occurs on the right side of the character.)
  762. With this change, the interfaces also change.  Following are both the old and new definitions in Pascal and C respectively:
  763. Old Definition
  764. FUNCTION Pixel2Char(textBuf: Ptr;textLen: INTEGER;slop: INTEGER;pixelWidth: INTEGER;
  765.                    VAR leftSide: BOOLEAN): INTEGER;
  766. pascal short Pixel2Char(Ptr textBuf,short textLen,short slop,short pixelWidth,
  767.                        Boolean *leftSide)
  768. New Definition
  769. FUNCTION Pixel2Char(textBuf: Ptr;textLen: INTEGER;slop: INTEGER;pixelWidth: INTEGER;
  770.                    VAR leadingEdge: BOOLEAN): INTEGER;
  771. pascal short Pixel2Char(Ptr textBuf,short textLen,short slop,short pixelWidth,
  772.                        Boolean *leadingEdge)
  773. The value of the leadingEdge flag is True if a mouse-down occurs on the leading edge of the character in its direction (e.g., the left side for a left-to-right script (Roman) and the right side for a right-to-left one (Arabic or Hebrew)).  Figure 1 illustrates these differences.
  774. This Note describes the way script systems should work; however, in some systems, the values of leadingEdge and character offset are undefined when the pixelWidth is outside the boundaries of the text.
  775. You define the start of a right-to-left line to be on the right and the end to be on the left; therefore, it follows that the start of a left-to-right line is on the left, while the end is on the right.  The values at the start of a line should be False for leadingEdge and zero for character offset.  The values at the end are True for leadingEdge and the character offset is the total byte count of that line.  You should check for these out-of-bounds conditions explicitly and perform the appropriate actions.  This change will appear in the next version of the Script Manager documentation.
  776. Figure 1–Pixel2Char leadingEdge Flag
  777. Accessing the Script Manager Print Action Routine
  778. Text        M.TE.PrintAction
  779. Revised by:        March 1988
  780. Written by:    Mark Davis    November 1987
  781. This technical note describes how Print Drivers can access the Script Manager Print Action routine to print unconventional text, such as Japanese or Arabic.
  782. General Notes
  783. Scripts such as Japanese or Arabic modify the normal QuickDraw text handling in order to represent text properly. On the screen, this is done by trapping StdText and StdTxtMeasure, and transforming the text before printing. For example, for Hebrew or Arabic the text might be reversed, since text normally goes from right to left in those scripts.
  784. Print drivers require slightly different handling, for two reasons:
  785. 1. A print driver might not call the standard QuickDraw procedures. For example, the LaserWriter writes directly in PostScript instead.
  786. 2. A print driver might need to format the text, for accurate line-layout. In this case, the text needs to be transformed before the driver performs line-layout. If the driver is spooling the text, and will replay the text a second time, the text cannot be transformed a second time, since that would ruin the appearance.
  787. For example, the ImageWriter driver calls QuickDraw procedures twice, once to spool and once to unwind the spooling. The text must be transformed when spooling, so that line layout can be done, but when unwinding, the transformation must be turned off completely.
  788. Note that some drivers, such as the LaserWriter, use QuickDraw re-entrantly: the application program calls a QuickDraw routine, which is directed to the driver’s grafProcs, which in turn call QuickDraw internally to put up status messages on the screen. The Print Action procedure handles the text properly so that the text transformations are enabled during the re-entrant calls, so that the status messages will be properly formatted.
  789. When To Call the Print Action Routine
  790. The Script Manager Print Action routine allows the print driver to be independent of the particular scripts being used. The printing driver should call this routine whenever it changes the grafProcs in the printing grafPort. The Print Action routine will then substitute grafProcs of its own in the grafProcs record, saving the original routine addresses.
  791. The Print Action routine will actually call a Print Action routine for each script system that is currently installed. Each of the script Print Action routines will do the appropriate tasks for its system.
  792. Calling the Print Action Routine
  793. To call the Print Action routine, the driver should use the following code:
  794. intlGlobals    equ    $ba0    ; international globals
  795. printActionOff    equ    $16    ; offset to PrintAction proc ptr
  796.     
  797. ; get procedure pointer to call
  798.     
  799.     tst.w    Rom85                ; on a Macintosh + or better?
  800.     blt.s    @PrintActionDone        ; no, skip
  801.     move.l    intlGlobals,d2        ; get international globals
  802.     ble.s    @PrintActionDone        ; not there, skip
  803.     move.l    d2,a0                ; in address register
  804.     move.l    printActionOff(a0),d2    ; get print action address
  805.     beq.s    @PrintActionDone        ; not there, skip
  806.     move.l    d2,a0                ; in address register
  807.     
  808. ; set up arguments to call
  809.     
  810.     move.l    <myPort>,d0            ; pass the port
  811.     move.w    <myVerb>,d1            ; pass the verb
  812.     jsr    (a0)                ; call the procedure
  813. @PrintActionDone
  814. Print Action Routine Verbs
  815. There are currently three verbs to pass to the Print Action routine.
  816.     paUnwindText        equ    –1
  817.     paSpoolText        equ    1
  818.     paNoQuickDraw        equ    3
  819. Use the paUnwind verb to ensure that the text is not transformed before your StdText procedure receives the text. This verb is used when playing back stored text that has already been transformed.
  820. The other two verbs (paNoQuickDraw and paSpoolText) are used to ensure that the text is transformed before your StdText procedure receives the text. The paSpoolText verb is used when your driver will use QuickDraw to image the text in the printing grafPort. The paNoQuickDraw verb is used when the text is not drawn into the printing port by going through QuickDraw (e.g. the LaserWriter). In that case some languages (e.g. Japanese) which use an extended font structure may need to recast the text calls as CopyBits calls.
  821. As mentioned above, some applications may call QuickDraw from within the driver, as when a status window is updated. During any StdTxtMeasure calls in the driver during the application’s call to StdText, the port is checked against the printer port. If they match, then the text is not transformed. Otherwise, the text is transformed.
  822. The solutions adopted by the Print Action routine assume that the print driver does not measure or draw text except within calls to StdTxtMeasure or StdText. If your driver does text buffering (as for line layout), make sure that any measurements are performed within these two calls. For example, you might buffer both the text and its screen width as measured by QuickDraw.
  823. Further Reference:
  824. •    The Script Manager 
  825. Safe cdevs
  826. Text        M.TE.SafeCDEV
  827. Written by:    John Harvey    August 1989
  828. This Technical Note describes a potential problem with Control Panel devices (cdevs) that contain EditText fields and presents a way to avoid it.
  829. The Control Panel chapter in Inside Macintosh, Volume 5 describes, in detail, how run-time errors are handled by the Control Panel and a cdev.  There is, however, a potential problem with cdevs that contain EditText items that this chapter does not cover.
  830. When a cdev is called by the Control Panel, the cdev’s 'DITL' resource is concatenated to the Control Panel’s 'DITL'.  The Control Panel then lets the Dialog Manager update the window.  If the cdev contains an item of type EditText, the Dialog Manager allocates and activates a TEHandle to be used for displaying and editing text.  All of this action happens before the cdev gets the initDev message from the Control Panel.
  831. As detailed in The Control Panel chapter, if an error occurs from which a cdev cannot recover, the cdev should dispose of any private memory and return the appropriate error code or a NIL value to the Control Panel.  The Control Panel then grays out the cdev’s area, displays the appropriate error dialog, and then deletes the items that were added to its 'DITL'.
  832. All of this is fine, except that the TEHandle does not get deallocated.  The EditText items get thrown away, including the strings in the item list that the Dialog Manager would use to store text entered into the EditText field, but the TEHandle stays there and stays active.  Figure 1 illustrates what this would look like.
  833. Figure 1–Erroneous Insertion Point
  834. So the Dialog Manager, knowing that it allocated a TEHandle for an item that was visible, goes merrily on its way flashing the insertion point.  The problem is not simply one of appearance.  If a user hits a key, the Dialog Manager tries to process the key-down event just as if the EditText item was still available, and this series of events causes a rather nasty crash.
  835. Fortunately, the solution for this problem is a very simple one.  If an EditText item is hidden with a _HideDItem call, the Dialog Manager does not consider it active and will not try to process key-down events for it.  So if your cdev contains EditText items, part of your error handling should be to first hide the EditText items with a call to _HideDItem before returning an error code or a NIL as the cdev’s function result.
  836. Further Reference:
  837. •    Inside Macintosh, Volume I, The Dialog Manager
  838. •    Inside Macintosh, Volume IV, The Dialog Manager
  839. •    Inside Macintosh, Volume V, The Control Panel
  840. Script Manager Q&As
  841. Text        M.TX.ScriptMgr.Q&As
  842. Revised by:    Developer Support Center    November 1992
  843. Written by:    Developer Support Center    October 1990
  844. This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
  845. Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
  846. New Q&As and Q&As revised this month are marked with a bar in the side margin.
  847. Using FormatXToStr and FormatStrToX with Pascal switches
  848. Written:    12/10/90
  849. Last reviewed:    8/1/92
  850. Why do the FormatXToStr and FormatStrToX Script Manager routines stop working when I use the Pascal -MC68881 switch?
  851. ___
  852. Regular SANE extended numbers are 10 bytes long while MC68881 extended numbers are 12 bytes long, and the extra two bytes are right in the middle of every 68881 extended number. Appendix G “The SANE Library” in the Macintosh Programmer’s Workshop (MPW) Object Pascal version 3.1 manual goes into detail about this. The FormatX2Str and FormatStr2X parse the extended number you pass them directly, and they can only parse 10-byte extended numbers. Fortunately, you can still use the -mc68881 option with these routines as long as you convert any extended numbers to 80-bit extended numbers before passing them to FormatX2Str and FormatStr2X. The SANE.p unit has routines to do this called X96toX80 and X80toX96 (incorrectly documented as X96to80 and X80to96 in the MPW Object Pascal manual). Because the extended80 and extended96 types aren’t equivalent to the extended type as far as Object Pascal is concerned, you have to redeclare FormatX2Str and FormatStr2X to take these types. You can do this as follows:
  853. FUNCTION FormatX2Str80 (x:             extended80;
  854.                         myCanonical:   NumFormatString;
  855.                         partsTable:    NumberParts;
  856.                         VAR outString:  Str255):  FormatStatus;
  857.     INLINE $2F3C,$8210,$FFE8,$A8B5;
  858. FUNCTION FormatStr2X80 (source:      Str255;
  859.                         myCanonical:  NumFormatString;
  860.                         partsTable:  NumberParts;
  861.                         VAR x:       extended80):  FormatStatus;
  862.     INLINE $2F3C,$8210,$FFE6,$A8B5;
  863. Call these routines instead of the originals. To call FormatX2Str80, all you have to do is this:
  864. VAR
  865.    x:             extended80; {96-bit extended number}
  866.    myCanonical:   NumFormatString;
  867.    partsTable:    NumberParts;
  868.    outString:     Str255
  869. result := FormatX2Str80 (X96toX80 (x), myCanonical, partsTable, outString);
  870. Calling FormatStr2X80 is just slightly more complicated because the extended number is passed by reference:
  871. VAR
  872.    x:           extended;   {96-bit extended number}
  873.    x80:         extended80; {80-bit extended number}
  874.    source:      Str255;
  875.    myCanonical:  NumFormatString;
  876.    partsTable:  NumberParts;
  877. x80 := X96toX80 (x);
  878. result := FormatStr2X80 (theString, realCanon, PartsTable, x80);
  879. x := X80toX96 (x80);
  880. You should find that these calls now work properly with the -mc68881 option
  881. set. This of course means that you’ll need two versions of the source code; one with the calls to convert between 96-bit and 80-bit extended numbers for use with the -mc68881 option and another one which just uses plain old 80-bit extended numbers for use when the -mc68881 option is turned off.
  882. X-Ref:
  883. Inside Macintosh Volume VI, page 14-49.
  884. String2Date and Date2Secs conversion surprises
  885. Written:    9/17/91
  886. Last reviewed:    8/1/92
  887. String2Date and Date2Secs treat all dates with the year 04 to 10 as 2004 to 2010 instead of 1904 to 1910.
  888. ___
  889. This is correct; the Script Manager treats two-digit years less than or equal to 10 as 20xx dates if the current year is between 1990 and 1999, inclusive. Basically, it just assumes that you’re talking about 1-20 years in the future, rather than 80-100 years in the past. The same is true of two-digit 9x dates, when the current year is less than or equal to xx10. Thus, in 2003, the date returned when 3/7/94 is converted will be 1994, not 2094. This is all documented in “Worldwide Development: Guide to System Software,” available from APDA.
  890. FormatX2Str strings
  891. Written:    11/6/91
  892. Last reviewed:    8/1/92
  893. Using the Script Manager to convert numbers to strings and vice versa, in any language, what’s the best way to create the string to pass to FormatX2Str? Will strings using the characters: “#” or “0” or “.” or “,” work no matter what script is currently running, and if not, what can I do?
  894. ___
  895. The number format string and canonical number format string mechanisms that you use with FormatX2Str and its kin is a strange design, for exactly the reason that you asked about. The number format string (the one with the characters such as “#” and “0”) does not necessarily work right regardless of the current script. In fact, it doesn’t even necessarily work right between localized versions within one script system. The canonical number format string does work between localized systems and between script systems. The strange thing is there’s an easy way to store number format strings (usually in a 'STR ' resource), but no obvious way to store canonical number format strings. Here’s what you can do when converting between numbers and strings:
  896. When you convert a number format string to a canonical number format string with Str2Format on a U.S. system, it converts it from something like “###.###” to a canonical number format string that looks something like, “three digits, a decimal point, and three digits.” On a German system, that same number format string would be converted to “three digits, a thousands separator, and three digits.”
  897. What you can do to get around this is to save the canonical number format string in a resource instead of the number format string. The canonical string stores things in a language- and script-independent way. Create this resource by writing a trivial utility program that takes a number format string and calls Str2Format to convert it into a canonical number format string, and then copy this into a handle and save it as a resource of a custom type, like 'NUMF'. In your real program, load the 'NUMF' resource, lock it, and then pass the dereferenced handle to FormatX2Str and FormatStr2X.
  898. You can see this done in the ProcDoggie Process Manager sample from the 7.0 Golden Master CD. Take a look at the SetUpProcessInfoItems procedure in UProcessGuts.inc1.p file. You’ll see that the 'NUMF' resource is loaded, locked, and then passed to FormatX2Str. The result is displayed in the Process Information window.
  899. If your program is localized by nonprogrammers, then you might want to provide the utility that converts a number format string to a canonical number format string resource just in case they have to change the entire format of the string. Then they can install the new 'NUMF' (or whatever you choose) resource as part of the localization process.
  900. Code for truncating a multi-byte character string
  901. Written:    1/24/92
  902. Last reviewed:    8/1/92
  903. I create a Macintosh file name from another file name. Since I am adding information to the name, I must make sure that it is within the 31 chars maximum allowed by the operating system. What I need is the equivalent of the TruncText command, except instead of dealing with pixel width, I want the width to be number of characters (31). I can trunc myself, but I’d rather do a proper “smTruncMiddle” and have it nicely internationalized.
  904. ___
  905. If you’re going to be adding a set number of bytes to the end of a existing string and you don’t want the localized ellipsis (from the 'itl4' resource) between the truncated string and your bytes, then you can use this routine:
  906. PROCEDURE TruncPString (VAR theString: Str255; maxLength: Integer);
  907. { This procedure truncates a Pascal string to be of length maxLength or }
  908. { shorter. It uses the Script Manager charByte function to make sure }
  909. { the string is not broken in the middle of a multi-byte character. }
  910.   VAR
  911.     charType: Integer;
  912.   BEGIN
  913.     IF Length(theString) > maxLength THEN
  914.       BEGIN
  915.         charType := CharByte(@theString[1], maxLength);
  916.         WHILE ((charType < 0) OR (charType > 1)) AND (maxLength <> 0) DO
  917.           BEGIN
  918.             maxLength := maxLength - 1;
  919.             charType := CharByte(@theString[1], maxLength);
  920.           END;
  921.         theString[0] := chr(maxLength);
  922.       END;
  923.   END;
  924. If you want the localized ellipsis (from the 'itl4' resource) between the truncated string and your bytes, or you want the localized ellipsis in the middle of the combined strings truncated to a specific length, then you can use this routine:
  925. FUNCTION TruncPString (maxLength: Integer; VAR theString: Str255; 
  926. truncWhere: TruncCode): Integer;
  927. { This function truncates a Pascal String to be of length maxLength or }
  928. { shorter. It uses the Script Manager TruncString function which adds }
  929. { the correct tokenEllipsis to the middle or end of the string. See }
  930. { Inside Macintosh Volume VI, pages 14-59 and14-60 for more info. }
  931.   VAR
  932.     found: Boolean;
  933.     first, midPoint, last: Integer;
  934.     tempString: Str255;
  935.     whatHappened: Integer;
  936.   BEGIN
  937.     found := FALSE;
  938.     first := 0;
  939.     last := TextWidth(@theString[1], 0, Length(theString));
  940.     IF Length(theString) > maxLength THEN
  941.       BEGIN
  942.         WHILE (first <= last) AND NOT found DO
  943.           BEGIN
  944.             tempString := theString; { tempString gets destroyed every }
  945.                                      { time through }
  946.             midPoint := (first + last) DIV 2;
  947.             whatHappened := TruncString(midPoint, tempString, truncWhere);
  948.             IF whatHappened < smNotTruncated THEN
  949.               BEGIN { ERROR, bail out now }
  950.                 TruncPString := whatHappened; { return error }
  951.                 Exit(TruncPString);
  952.               END
  953.             ELSE IF Length(tempString) = maxLength THEN
  954.               found := TRUE
  955.             ELSE IF Length(tempString) > maxLength THEN
  956.               last := midPoint - 1
  957.             ELSE
  958.               first := midPoint + 1;
  959.           END;
  960.         theString := tempString;
  961.         TruncPString := whatHappened; { will always be smTruncated }
  962.                                       { in this case }
  963.       END
  964.     ELSE
  965.       TruncPString := smNotTruncated; { the string wasn't too long }
  966.   END;
  967. Character type and subtype values within the Kanji system
  968. Written:    11/17/89
  969. Last reviewed:    8/1/92
  970. What are the values of character type and subtype with the Macintosh Kanji system?
  971. ___
  972. For Roman, these are the values of character type:
  973.     Punctuation         0
  974.     ASCII               1
  975.     European            7
  976. For KanjiTalk, the values are the same as Roman, with the addition of:
  977.     Katakana            2
  978.     Hiragana            3
  979.     Kanji               4
  980.     Greek               5
  981.     Russian (Cyrillic)  6
  982. In Roman, the subtype field is interpreted as:
  983.     Normal punctuation  0
  984.     Numeric             1
  985.     Symbols             2
  986.     Blanks              3
  987. The KanjiTalk subtype values are the same as Roman except if the character type is Kanji, in which case the subtype field takes these values:
  988.     JIS Level 1         0
  989.     JIS Level 2         1
  990.     JIS User Character  2
  991. Finally, for KanjiTalk, the character direction field is replaced by the In-ROM field. It is 1 if the character is in the ROM card and 0 otherwise.
  992. Script Manager NMeasureJust documentation fix
  993. Written:    7/21/92
  994. Last reviewed:    9/15/92
  995. The Script Manager’s NMeasureJust call seems to work differently depending on our main script (Roman versus Hebrew, for example). Please take a look at the following code and tell me if I’m doing something wrong:
  996. {
  997.    ....
  998.    Fixed slop  = 0;
  999.    Point   numer   = {1,1};
  1000.    Point   denom   = {1,1};
  1001.    ::NMeasureJust ((Ptr) charBuffer, (short) charCount,slop,(Ptr) charLocs,
  1002.                        smOnlyStyleRun, numer, denom);
  1003.    if (charLocs[0]) {
  1004.        // Under Hebrew system NMeasureJust acts differently than described in
  1005.        // Inside Macintosh Volume VI; first entry in charLocs array containes width
  1006.        // of last character and last entry in charLocs array containes zero.
  1007.        charLocs[charCount] = charLocs[0];
  1008.        charLocs[0] = 0;
  1009.    };
  1010.    ....
  1011. }
  1012. ___
  1013. The truth is that Inside Macintosh Volume VI is incorrect, and NMeasureJust is working correctly, even though the results seem to defy any kind of sense. Here’s how NMeasureJust works:
  1014. NMeasureJust actually puts into the first entry of the charLocs array the pixel offset from the left end of the text to the leading edge of the first character, regardless of the active script system. For Roman text in a Roman script system, that’s easy: it’s always zero. For Hebrew text in a Hebrew script system, the leading edge of the first character is on the right edge of the text, so NMeasureJust puts the pixel distance between the left edge of the text to the right edge of the text——the same thing as the entire width of the text. Each successive entry in the charLocs array is smaller than the previous entry because we’re gradually moving to the left edge of the text as we move through each successive character. The trailing edge of the last character is at the left edge of the string, and so the last entry in the charLocs array is zero.
  1015. What if you pass in text that contains both Roman and Hebrew text? This text contains a direction boundary, and NMeasureJust can sense this. For this case, NMeasureJust puts into the charLocs array a series of decreasing values for the right-to-left characters, and a series of increasing values for the left-to-right characters.
  1016. You’re probably passing Roman text (ASCII codes less than 127) to NMeasureJust with the Hebrew script system active to get the results that you reported. This case includes two direction boundaries: one at the beginning that’s right-to-left and contains no characters, one that’s left-to-right and contains all your Roman characters, and finally one that’s right-to-left and contains no characters. The first entry in the charLocs array measures the first right-to-left direction run even though it contains no characters, and so it contains the position of the right edge of your text. The last entry in the charLocs array is zero because it measures the last right-to-left direction run, which again contains no characters. All the charLocs entries between the first and the last measure the positions of the left-to-right, Roman characters, and so you get a series of increasing values. This is just a special case of passing text that contains direction boundaries to NMeasureJust.
  1017. Interfacing a Macintosh application with Map CDEV data
  1018. Written:    8/17/92
  1019. Last reviewed:    10/11/92
  1020. How can I provide my users with a “hook” to access the geographical database in Apple’s “Map” Control Panel from my application?
  1021. ___
  1022. There’s no supported way of accessing the geographical database contained in the “Map” Control Panel. Here are some hints, however (just to satisfy your curiosity):
  1023. The data are stored in a resource of type 'CTY#', ID=-4064, in the Map cdev. The resource format is a list of word aligned (variable length) city entries, preceded by an integer indicating the number of entries. Each entry has the format
  1024.  [Integer]    length in bytes of the entry 
  1025.  [Longint]   latitude in Fract; north = +
  1026.  [Longint]   longitude in Fract; east = +
  1027.  [Longint]   GMT difference in seconds; east = +
  1028.  [Longint]  (reserved; set to 0)
  1029.  [PascalString]  name of the city.
  1030. Script Manager Variables
  1031. Text        M.TE.ScriptVars
  1032. Written by:    John Harvey & Peter Edberg    June 1989
  1033. This Technical Note describes, in detail, the local and global script variables.
  1034. Introduction
  1035. The Script Manager maintains a number of global variables which can be read with the routine _GetEnvirons.  These variables can be set by a corresponding routine, _SetEnvirons.  In addition, each script interface system maintains variables of its own.  These are referred to as local variables in Inside Macintosh, Volume V-293, The Script Manager, and are read by _GetScript and set by _SetScript.
  1036. Think of it like this:  the Script Manager maintains an environment in which different script interfaces can run.  The global variables are used to set up and maintain the environment (thus the names for the routines _GetEnvirons and _SetEnvirons), and the local variables control how the script itself works (so we have _GetScript and _SetScript).
  1037. Global Variables
  1038. When you call _GetEnvirons or _GetScript, you describe the variable you are interested in with a verb.  A verb is simply an integer constant which the Script Manager uses to figure out which variable you want to read or set.  The z in Inside Macintosh, V-313, gives incorrect names and descriptions for some of the _GetEnvirons and _SetEnvirons verbs.  Table 1 provides correct descriptions.
  1039. Constant    Value    Meaning
  1040. smVersion    0    Script Manager version number
  1041. smMunged    2    Global modification count
  1042. smEnabled    4    Script count; 0 if Script Manager not
  1043.         enabled
  1044. smBidirect    6    Bidirectional script flag
  1045. smFontForce    8    Force font flag
  1046. smIntlForce    10    Force international utilities flag
  1047. smForced    12    Current script forced to system script
  1048. smDefault    14    Current script defaulted to Roman
  1049.         script
  1050. smPrint    16    Print action vector
  1051. smSysScript    18    Preferred system script
  1052. smLastScript    20    Last keyboard script
  1053. smKeyScript    22    Keyboard script
  1054. smSysRef    24    System folder volRefNum
  1055. smKeyCache    26    [Obsolete, do not use]
  1056. smKeySwap    28    Keyboard swapping resource handle
  1057. smGenFlags    30    General flags
  1058. smOverride    32    Script override flags
  1059. smCharPortion    34    Ch vs Sp Extra proportion, 4.12 fixed
  1060. Table 1–Verbs for _GetEnvirons and _SetEnvirons
  1061. The descriptions in the table are still a bit sketchy.  The next section describes each variable in more detail and describes the size of each global.
  1062. Byte or word globals are mapped to the low-order byte or word of the LongInt returned by _GetEnvirons, with the high-order parts set to zero. Similarly, for these globals _SetEnvirons ignores all but the appropriate part (low-order byte or word) of its params value.
  1063. Verb Name    Bytes    Brief Description
  1064. smVersion    2    Script Manager version number
  1065. At boot time, the version global is initialized to the value SMgrVers.  The high byte is the major version number and is defined in the MPW interface files.  The low byte is updated when any changes are made to the Script Manager.
  1066. smMunged    2    Global modification count
  1067. The munged global is initialized to zero at boot time and incremented when:
  1068. •    _KeyScript changes the key script and updates smKeyScript and smLastScript
  1069. •    _SetEnvirons is used to change a Script Manager global
  1070. smEnabled    1    Script count; 0 if Script Manager not enabled
  1071. At boot time or switch-launch time, the enabled global is initialized to zero, then incremented for each script that is installed and enabled.  Since the Roman script system should always be installed by the Script Manager, a value of zero indicates that the Script Manager is not enabled.
  1072. It should be noted that older versions of the Script Manager treated this as a Boolean.  In other words, if there was more than one script installed, _GetEnvirons(smEnabled) would return 255 (when _GetEnvirons returns a Boolean value $FF represents true).
  1073. For this reason, when testing to see if more than one script is installed, it is best to test as follows:
  1074.     scriptsinstalled := GetEnvirons(smEnabled);
  1075.     IF scriptsinstalled > 1 THEN  
  1076.     {more than one script available, use Chartype, etc.}
  1077. smBidirect    1    Bidirectional script flag
  1078. The bidirectional global indicates that at least one bidirectional script is installed.  It should be set to true ($FF) by the Arabic and Hebrew script systems.  This is not presently done, but will be corrected in future versions of these systems.
  1079. smFontForce    1    Force font flag
  1080. smIntlForce    1    Force international utilities flag
  1081. smForced    1    Current script forced to system script
  1082. smDefault    1    Current script defaulted to Roman script
  1083. At boot time, FontForce and IntlForce are set from the 'itlc' resource, and Forced and Default are set to zero.  These are all flags with the value zero for false and $FF for true.  FontForce and IntlForce control the operation of the _FontScript, _Font2Script, and _IntlScript routines.  Forced and Default report the actions of these routines.
  1084. Setting FontForce to true forces Roman fonts to be interpreted as belonging to the system script.  This is for compatibility with applications that hard-code font numbers.
  1085. IntlForce determines the behavior of the _IUGetIntl call.  When intlforce is set to true, _IUGetIntl will return a handle to the international resources (of type 'itlx' where x is 0-2) for the system script.  When IntlForce is false, the _IUGetIntl will use the font of the current port to determine the appropriate resources to fetch.  Thus date formats, sorting, etc. can reflect the current script.
  1086. smPrint    4    Print action vector
  1087. Print action routine vector; set up at boot time. See M.TE.PrintAction.
  1088. smSysScript    2    Preferred system script
  1089. smLastScript    2    Last keyboard script
  1090. smKeyScript    2    Keyboard script
  1091. At boot time and switch-launch time, SysScript and KeyScript are set from the SysScript field of the 'itlc' resource if that script is installed and enabled; otherwise, SysScript and KeyScript are set to Roman (without setting Default).
  1092. The KeyScript global is the current keyboard script, tested and updated by the _KeyScript routine.  When _KeyScript changes KeyScript, it moves the old value to LastScript.  _KeyScript can also swap the current key script with the last one, which it retrieves from LastScript.  The KeyScript value is also used to get the proper keyboard script icon and to retrieve the proper 'KCHR'.
  1093. SysScript specifies the system script, and is used, for example, by _FontScript, _Font2Script, and _IntlScript.
  1094. KeyScript, LastScript, and SysScript always contain integers that correspond to a script number.  Script numbers are documented in The Script Manager chapter of Inside Macintosh, Volume V-293.
  1095. smSysRef    2    System folder volRefNum
  1096. Set from the global BootDrive at boot time and switch-launch time.  SysRef was originally a way of testing for vanilla launch versus switch launch; now the Enabled global is used for that purpose.
  1097. smKeyCache    2    [Obsolete, do not use]
  1098. smKeySwap    4    Keyboard swapping resource handle
  1099. The 'KSWP' resource handle is put here at boot time and switch-launch time.  A 'KSWP' resource contains a table of key sequences that will cause the  currently installed 'KCHR' (keyboard mapping table) to change to the preferred system 'KCHR', switch to the Roman 'KCHR', or rotate among the available 'KCHR' resources.  The table includes the virtual key code and the modifier keys.  The following is the 'KSWP' resource for the Kanji script interface system.
  1100. resource 'KSWP' (0, sysheap) {
  1101.     {/* array: 3 elements */
  1102.         /* [1] */
  1103.         Rotate, 49, controlOff, optionOff, shiftOff, commandOn,
  1104.         /* [2] */
  1105.         System, 70, controlOff, optionOff, shiftOff, commandOn,
  1106.         /* [3] */
  1107.         Roman, 66, controlOff, optionOff, shiftOff, commandOn
  1108.     }
  1109. };
  1110. The resource says rotate 'KCHR' resources if a Space–Command key occurs, switch to the system 'KCHR' on  keypad plus (+)–Command key, and switch to the Roman 'KCHR' on keypad asterisk (*)–Command key.
  1111. smGenFlags    4    General flags
  1112. Only the two high-order bits are defined (in the file ScriptEqu.a), as follows:
  1113. smfShowIcon = 31    (show icon even if only one script)
  1114. smfDualCaret = 30    (use dual caret for mixed direction text)
  1115. The high-order byte of smgrGenFlags, containing these flags, should be setup from the flags byte in the 'itlc' resource.  This is not presently done, but will be fixed in future versions of the Script Manager.
  1116. The following MPW Pascal procedure demonstrates how to get script 'SICN' resources to display even if there is only one script system installed.
  1117. PROCEDURE SetSICN;
  1118. VAR
  1119.     SICNstate: Longint;
  1120.     err: Oserr;
  1121.     
  1122. BEGIN
  1123.     SICNstate := GetEnvirons(smGenFlags);
  1124.     BSET(SICNstate,smfShowIcon);
  1125.     
  1126.     err := SetEnvirons(smGenFlags,SICNstate);
  1127. END;
  1128. smOverride    4    Script override flags
  1129. At present, this is not set or used by the Script Manager.  It is, however, reserved for future improvements.
  1130. smCharPortion    2    Ch vs Sp Extra proportion, 4.12 fixed
  1131. This is 16-bit fixed-point value in 4.12 format (e.g., 10% = $0199).  It is initialized to 10 percent at boot time.  It is intended to be used by script systems to allocate space among intercharacter spacing and interword spacing when justifying text.
  1132. A 16-bit fixed-point value in 4.12 format is similar to the fixed-point number type defined on page I-79 of Inside Macintosh .  The obvious difference being that  it is only 16 bits long.  The integer part of the value is stored in the high four bits, and the fractional part is stored in the low 12 bits.
  1133. 16-bit Fixed-Point Number in 4.12 format
  1134. Local Variables
  1135. Every script interface system has local variables.  Page V-132 of Inside Macintosh lists verbs which are constants that indicate which variable you want to read or set.  The table of constants used to access the local variable, although more accurate than the global table, does contain a few inaccuracies.  In addition four new constants have been added.  Table 2 gives the correct constants.
  1136. Constant    Value    Meaning
  1137. smScriptVersion    0    Script Interface version number
  1138. smScriptMunged    2    Local modification count
  1139. smScriptEnabled    4    Script Enabled Flag
  1140. smScriptRight    6    Right to Left Flag
  1141. smScriptJust    8    Justification Flag
  1142. smScriptRedraw    10    Word Redraw Flag
  1143. smScriptSysFond    12    Preferred System Font
  1144. smScriptAppFond    14    Preferred Application Font
  1145. smScriptNumber    16    Script 'itl0' ID
  1146. smScriptDate    18    Script 'itl1' ID
  1147. smScriptSort    20    Script 'itl2' ID
  1148. smScriptFlags    22    Script Flags Word (new)
  1149. smScriptToken    24    'itl4' ID number (new)
  1150. smScriptRsvd    26    Reserved
  1151. smScriptLang    28    Script’s language code (new)
  1152. smScriptNumDate    30    Number/date representation codes
  1153.         (new)
  1154. smScriptKeys    32    Script 'KCHR' ID
  1155. smScriptIcon    34    Script 'SICN' ID
  1156. smScriptPrint    36    Script printer action routine
  1157. smScriptTrap    38    Trap entry pointer
  1158. smScriptCreator    40    Script file creator
  1159. smScriptFile    42    Script file name
  1160. smScriptName    44    Script name
  1161. Table 2–Local Variable Constants
  1162. Here again the descriptions are a little terse.  The following section describes each variable in more detail and describes the size of each variable.
  1163. Verb Name    Bytes    Brief Description
  1164. smScriptVersion    4    Script Interface version number
  1165. When the script interface is loaded, this is set to the current version number.
  1166. smScriptMunged    2    Local modification count
  1167. This variable is incremented each time _SetScript is called.
  1168. smScriptEnabled    1    Script Enabled Flag
  1169. A Boolean which indicates whether the script has been enabled.  Set to $FF when enabled and zero when not enabled.
  1170. smScriptRight    1    Right to Left Flag
  1171. A Boolean indicating if text should be drawn right to left or left to right.  It is set to $FF for right to left text (Arabic and Hebrew scripts) and zero for left to right (Roman).
  1172. smScriptJust    1    Justification Flag
  1173. A byte flag which describes how text should be justified.  The possible settings correspond to the justification flags used by TextEdit.
  1174.     0    = left justification
  1175.     1    = center justified
  1176.     -1    = right justified
  1177. smScriptRedraw    1    Word Redraw Flag
  1178. A byte flag describing how much of a line should be redrawn when text is being entered.
  1179.     0    Only draw a character
  1180.     1    Redraw the entire word
  1181.     -1    Redraw the entire line (Arabic)
  1182. smScriptSysFond    2    Preferred System Font
  1183. This is the font family ID for the preferred System Font.  In a Roman system, ScriptSysFond is 0, the family ID for Chicago.
  1184. smScriptAppFond    2    Preferred Application Font
  1185. Font family ID for the preferred Application Font.  In a Roman system, ScriptAppFond is 3, the family ID for Geneva.
  1186. smScriptNumber    4    Script 'itl0' ID
  1187. Resource ID of 'itl0' for this script.  The 'itl0' resource describes how numbers and times should be displayed.  The resource ID should match the country version code for a given country.
  1188. smScriptDate    4    Script 'itl1' ID
  1189. Resource ID of the 'itl1' for this script.  The 'itl1' describes how dates should be displayed.
  1190. smScriptSort    4    Script 'itl2' ID
  1191. Resource ID of the 'itl2' for this script.  The 'itl2' contains routines for sorting.  See M.TE.NewStringComp.
  1192. smScriptFlags    2    Script flags
  1193. This verb provides access to the script flags word, which contains bit flags that describe features of the script.  This word is initialized from the script’s 'itlb' resource.  Constants specifying the bit numbers are described in Table 3.
  1194.     Bit
  1195. Constant    Number    Description
  1196. smsfIntellCP    0    script has intelligent cut and paste
  1197. smsfSingByte    1    script has only single bytes
  1198. smsfNatCase    2    native characters have upper and lower case
  1199. smsfContext    3    contextual script (e.g., AIS-based)
  1200. smsfNoForceFont    4    will not force characters
  1201. smsfB0Digits    5    has alternative digits in B0-B9
  1202. smsfForms    13    uses contextual forms for letters
  1203. smsfLigatures    14    uses contextual ligatures
  1204. smsfReverse    15    reverses native text, right-left
  1205. Table 3–Constant Bit Numbers
  1206. smScriptToken    2    Script 'itl2' ID
  1207. Resource ID of the 'itl4' for this script.  The 'itl4' contains contains tables needed by the number formatting and conversion routines and the _intlTokenize routine.  See Script Manager 2.0, Interim Chapter.
  1208. smScriptRsvd    4    Reserved
  1209. smScriptLang    2    Script’s language code
  1210. This verb accesses a word which contains the current language code for the script.  The language codes are defined in the MPW interface files.
  1211. smScriptNumDate    2    Number and date representation codes
  1212. This verb accesses a word containing the number and date representation codes for the script.  The number representation code is in the high byte of the word, and the date code is in the low byte.
  1213. The possible values for number representations and date codes are declared as constants in the MPW interface files.
  1214. The number codes are:    and the date codes are:
  1215. intWestern = 0;        calGregorian = 0;
  1216. intArabic = 1;            calArabicCivil = 1;
  1217. intRoman = 2;        calArabicLunar = 2;
  1218. intJapanese = 3;        calJapanese = 3;
  1219. intEuropean = 4;        calJewish = 4;
  1220.                 calCoptic = 5;
  1221. smScriptKeys    4    Script 'KCHR' ID
  1222. Resource ID of preferred 'KCHR' resource.  The 'KCHR' resource is used to map virtual key codes into the correct character code.  See M.TB.KeyMapping.
  1223. smScriptIcon    4    Script 'SICN' ID
  1224. Resource ID of the small icon that is used to represent which country specific resources ('itl0', 'itl1', 'itl2', 'KCHR') are currently installed in the system.  Presently, the Roman system does not display the 'SICN'.  Arabic, Kanji, Chinese, and Hebrew interface systems do display this icon in the upper-right corner of the menu bar.
  1225. smScriptPrint    4    Script printer action routine 
  1226. Print action routine vector; setup when script is installed by Script Manager.  See M.TE.PrintAction.
  1227. smScriptTrap    4    Trap entry pointer
  1228. Pointer to Script dispatch routine.  Script Manager routines always belong to one of two groups.  The first group of routines are common to every script interface system, and the second group must be supplied by the script interface system.  This variable will point to a dispatch routine for the interface-supplied routines.  When you call _ScriptUtil, it looks at the selector that is passed and either calls a common routine or calls the routine whose address is stored in ScriptTrap.  The routine in smScriptTrap will then use the selector to vector to the correct routine.  In general, routines that display or measure text in some way will be supplied by the interface.
  1229. A list at the end of this Note indicates which routines are implemented by the Script Manager and which routines are supplied by a script interface system.
  1230. smScriptCreator    4    Script file creator
  1231. The four character creator type for the script interface’s file.  For Roman it is “ZSYS,” the same creator as any system file has.
  1232. smScriptFile    4    Script file name
  1233. A pointer to the a Pascal string which contains the name of the file containing the script interface system.  For the Roman SIS, it is System.
  1234. smScriptName    44    Script name
  1235. A pointer to a Pascal string which contains the script interface’s name.  For Roman it is naturally, “Roman.”
  1236. Who Does What?
  1237. Table 4 breaks the documented routines into common Script Manager routines and interface specific routines.
  1238. Common Routines    Interface Supplied
  1239. _FontScript    _CharByte
  1240. _IntlScript    _CharType
  1241. _KeyScript    _Pixel2Char
  1242. _GetEnvirons    _Char2Pixel
  1243. _SetEnvirons    _Transliterate
  1244. _Font2Script    _FindWord
  1245. _Format2Str    _HiliteText
  1246. _FormatStr2X    _DrawJust
  1247. _FormaX2Str    _MeasureJust
  1248. _GetFormatOrder    _ParseTable
  1249. _InitDateCache    _VisibleLength
  1250. _IntlTokenize    _FindScriptRun
  1251. _LongDate2Secs    _PortionText
  1252. _LongSecs2Date
  1253. _Str2Format
  1254. _String2Date
  1255. _String2Time
  1256. _StyledLineBreak
  1257. _ToggleDate
  1258.  
  1259. Table 4–Script Manager Routines and Interface Specific Routines
  1260. _GetScript and _SetScript, which return the values of local script variables, are implemented by the Script Manager for some verbs and the script interface system for others.
  1261. There is also a group of Script Manager routines which don’t use the _ScriptUtil trap, but are documented in The Script Manager chapter of Inside Macintosh, Volume V-293 or The Script Manager 2.0 Interim Chapter.  There routines are utilities that read and write to low-memory or PRAM.  It is important to use these routines when they are available.  That will allow Apple to modify where global variables, etc. are stored, and your application will remain compatible.  The utilities are:
  1262.     GetDefFontSize
  1263.     GetSysFont
  1264.     GetAppFont
  1265.     GetMBarHeight
  1266.     GetSysJust
  1267.     SetSysJust
  1268.     ReadLocation (documented in Interim Chapter)
  1269.     WriteLocation (documented in Interim Chapter)
  1270. Further Reference:
  1271. •    Inside Macintosh, Volume V-293, The Script Manager
  1272. •    M.TB.KeyMapping
  1273. •    M.TE.PrintAction
  1274. Modifying the Standard String Comparison
  1275. Text        M.TE.NewStringComp
  1276. Revised by:        March 1988
  1277. Written by:    Mark Davis
  1278.         Priscilla Oppenheimer    November 1987
  1279. This technical note describes how to modify the standard string comparison by constructing an itl2 resource. Developers may want to modify the standard string comparison if Apple’s comparison doesn’t meet their needs or if Apple has not written a string comparison routine for the language that concerns them.
  1280. General Structure
  1281. The itl2 resource contains a number of procedures that are used for accurate comparison of text by the International Utilities Package. Refer to Inside Macintosh, volume V for an explanation of the algorithm used. The default itl2 for standard English text, which does no special processing, has the following form:
  1282.     ; normal Include/Load statements
  1283.     Include 'hd:mpw:aincludes:ScriptEqu.a'
  1284.     Print    On,NoMDir
  1285.     String    AsIs
  1286. ;------------------------------------------------------------------------
  1287. ;     dispatch table at the front of the code.
  1288. ;------------------------------------------------------------------------
  1289. Intl1        Proc
  1290.     With    IUSortFrame,IUStrData
  1291. HookDispatch
  1292.     dc.w    ReturnEQ-HookDispatch    ; InitProc = 0
  1293.     dc.w    ReturnEQ-HookDispatch    ; FetchHook = 2
  1294.     dc.w    ReturnEQ-HookDispatch    ; VernierHook = 4
  1295.     dc.w    ReturnEQ-HookDispatch    ; ProjectHook = 6
  1296.     dc.w    ReturnEQ-HookDispatch    ; ReservedHook1 = 8
  1297.     dc.w    ReturnEQ-HookDispatch    ; ReservedHook2 = 10
  1298. ;------------------------------------------------------------------------
  1299. ; Some common exit points
  1300. ;------------------------------------------------------------------------
  1301. ReturnNE    
  1302.     tst.w     MinusOne        ; set cc NE
  1303.     rts
  1304. ReturnEQ
  1305.     cmp.w    d0,d0        ; set cc EQ
  1306.     rts
  1307. ;------------------------------------------------------------------------
  1308.     EndWith
  1309.     EndWith
  1310.     End
  1311. If modifications need to be made to the comparison process, then one or more of the dispatches will be modified to point to different routines:
  1312.     dc.w    InitProc-HookDispatch    ; InitProc = 0
  1313.     dc.w    FetchProc-HookDispatch    ; FetchHook = 2
  1314.     dc.w    VernierProc-HookDispatch    ; VernierHook = 4
  1315.     dc.w    ProjectProc-HookDispatch    ; ProjectHook = 6
  1316. There are a number of different changes that can be made to the comparison routines. Some of the common modifications include:
  1317.   1.    Comparing two bytes as one character
  1318.     Yugoslavian “l” < “lj” < “m”; Japanese…    [InitProc, FetchProc]
  1319.   2.    Comparing characters in different order
  1320.     Norwegian “z” < “å”                [ProjectProc]
  1321.   3.    Comparing one character as two
  1322.     German “ä” ≈ “ae”                [ProjectProc]
  1323.   4.    Ignoring characters unless strings are otherwise equal:
  1324.     “blackbird” < “black-bird” < “blackbirds”    [ProjectProc]
  1325.   5.    Changing the secondary ordering
  1326.     Bibliographic “a” < “A”            [VernierProc]
  1327. The comparison hook procedures are all assembly language based, with arguments described below. Since the routines may be called once per character in both strings, the routines should be as fast as possible.
  1328. The condition codes are used to return information about the status of the hook routine. Typically the normal processing of characters will be skipped if the CCR is set to NE, so the default return should always have EQ set. Each of these routines has access to the stack frame (A6) used in the comparison routine, which has the following form:
  1329. IUSortFrame    Record    {oldA6},Decrement
  1330. result    ds.w    1
  1331. argTop    equ    *
  1332. aStrText    ds.l    1
  1333. bStrText    ds.l    1
  1334. aStrLen    ds.w    1
  1335. bStrLen    ds.w    1
  1336. argSize    equ    argTop-*
  1337. return    ds.l    1
  1338. oldA6        ds.l    1
  1339. aInfo        ds    IUStrData
  1340. bInfo        ds    IUStrData
  1341. wantMag     ds.b    1    ; 1-MagStrig 0-MagIdString.
  1342. weakEq    ds.b    1        ; Signals at most weak equality
  1343. msLock    ds.b    1        ; high byte of master ptr.
  1344. weakMag     ds.b    1    ; -1 weak, 1 strong compare
  1345. supStorage    ds.b    18    ; extra storage.
  1346. localSize    equ    *    ; frame size.
  1347.         EndR
  1348. There are three fields in this frame that are of interest for altering text comparison. The supStorage field is an area reserved for use by the comparison hook procedures as they see fit. The aInfo and bInfo records contain information about the current byte positions in the two compared strings A and B, and information about the status of current characters in those string. The IUStrData record has the following form:
  1349. IUStrData    Record        0
  1350. curChar    ds.w        1    ; current character.
  1351. mapChar     ds.w        1    ; projected character.
  1352. decChar     ds.w        1    ; decision char for weak equality
  1353. bufChar     ds.b        1    ; buffer for expansion.
  1354. justAfter    ds.b        1    ; boolean for AE vs ligature-AE.
  1355. ignChar    ds.b        1    ; flag: ignore char.
  1356. noFetch    ds.b        1    ; flag: no fetch of next.
  1357. strCnt    ds.w            1    ; length word.
  1358. strPtr    ds.l            1    ; current ptr to string.
  1359.         EndR
  1360. The Init Procedure
  1361. The Init Procedure is used to initialize the comparison process. The main use for this procedure is for double-byte scripts. As an optimization, the International Utilities will perform an initial check on the two strings, comparing for simple byte-to-byte equality. Thus any common initial substrings are checked before the Init procedure is called. The string pointers and lengths in the IUStrData records have been updated to point just past the common substrings.
  1362. Languages such as Japanese or Yugoslavian, which may consider two bytes to be one character, may have to back up one byte, as shown below.
  1363. ;------------------------------------------------------------------------
  1364. ; Routine    InitProc
  1365. ; Input    A6          Local Frame
  1366. ; Output    CCR         NE to skip entire sort (usually set EQ)
  1367. ; Trashes    Standard regs:    A0/A1/D0-D2
  1368. ; Function    Initialize any special international hooks.
  1369. ;        Double-byte scripts must synchronize AInfo.StrPtr &
  1370. ;                  BInfo.StrPtr here!
  1371. ;------------------------------------------------------------------------
  1372. ; Note: this should also check for single-byte nigori or maru, as below
  1373. InitProc
  1374.     move.w    AStrLen(a6), d0    ; A length
  1375.     sub.w    AInfo.StrCnt(a6),d0    ; see if its changed
  1376.     beq.s    @FixB            ; A is done if not
  1377.     sub.l    #2,sp            ; return param
  1378.     move.l    AStrText(a6),-(sp)    ; textBuf
  1379.     move.w    d0,-(sp)        ; textOffset
  1380.     _CharByte
  1381.     tst.w    (sp)+            ; on character boundary?
  1382.     ble.s    @FixB            ; yes, continue
  1383.     sub.l    #1,AInfo.StrPtr(A6)    ; adjust pointer
  1384.     add.w    #1,AInfo.StrCnt(A6)    ; adjust count
  1385. @FixB
  1386.     move.w    BStrLen(a6), d0    ; B length
  1387.     sub.w    BInfo.StrCnt(a6),d0    ; see if its changed
  1388.     beq.s    Quit Init        ; B is done if not
  1389.     sub.l    #2,sp            ; return param
  1390.     move.l    BStrText(a6), -(sp)    ; textBuf
  1391.     move.w    d0, -(sp)        ; textOffset
  1392.     _CharByte
  1393.     tst.w    (sp)+            ; on character boundary?
  1394.     ble.w    @QuitInit        ; yes, continue
  1395.     sub.l    #1,BInfo.StrPtr(A6)    ; adjust pointer
  1396.     add.w    #1,BInfo.StrCnt(A6)    ; adjust count
  1397. @QuitInit
  1398.     bra.s    ReturnEQ        ; return to the caller.
  1399.     EndWith
  1400. The Fetch Procedure
  1401. The Fetch Procedure is used to fetch a character from a string, updating the pointer and length to reflect the remainder of the string. For example, the following code changes the  text comparison for Yugoslavian:
  1402. ;------------------------------------------------------------------------
  1403. ; Routine    FetchProc
  1404. ; Input    A2          String Data Structure
  1405. ;        A3          String pointer (one past fetched char)
  1406. ;         A6          Local Frame
  1407. ;        D4.W        Character: top byte is fetched character, bottom
  1408. ;                              is zero
  1409. ;        D5.B        1 if string is empty, otherwise 0
  1410. ; Output    D4.W        Character: top byte set to character, bottom to
  1411. ;                    extension
  1412. ;        D5.B        1 if string is empty, otherwise 0
  1413. ; Trashes    Standard regs:    A0/A1/D0-D2
  1414. ; Function    This routine returns the characters that are fetched from
  1415. ;        the string, if they are not just a sequence of single bytes.
  1416. ;------------------------------------------------------------------------
  1417. FetchProc
  1418.     tst.b    d5            ; more characters in string?
  1419.     bne.s    ReturnEq        ; no -> bail out.
  1420.     move.w    d4,d0            ; load high byte.
  1421.     move.b    (a3),d0        ; load low byte.
  1422.     
  1423.     lea    pairTable,a1        ; load table address
  1424. @compareChar
  1425.     move.w    (a1)+,d1        ; pair = 0?
  1426.     beq.s    ReturnEq        ; yes -> end of table.
  1427.     cmp.w    d0,d1            ; legal character pair?
  1428.     bne.s    @compareChar        ; no -> try the next one.
  1429.     add.w    #1,a3            ; increment pointer.
  1430.     sub.w    #1,StrCnt(a2)        ; decrement length.
  1431.     addx.w    d5,d5            ; empty -> set the flag.
  1432.     move.w    d0,d4            ; copy character pair.
  1433.     rts                ; return to caller with CCR=NE
  1434. pairTable
  1435.     dc.b    'Lj'            ; Lj
  1436.     dc.b    'LJ'            ; LJ
  1437.     dc.b    'lJ'             ; lJ
  1438.     dc.b    'lj'            ; lj
  1439.     
  1440.     dc.b    'Nj'            ; Nj
  1441.     dc.b    'NJ'            ; NJ
  1442.     dc.b    'nJ'            ; nJ
  1443.     dc.b    'nj'            ; nj
  1444.     dc.b    'D', $be        ; Dz-hat
  1445.     dc.b    'D', $ae        ; DZ-hat
  1446.     dc.b    'd', $ae        ; dZ-hat
  1447.     dc.b    'd', $be        ; dz-hat
  1448.     DC.B    $00, $00        ; table end
  1449. FetchProc
  1450.     with        IUStrData
  1451.     tst.b        d5            ; empty string?
  1452.     bne.s        ReturnEq        ; exit if length = 0
  1453.     
  1454. ; if we have a double-byte char, add the second byte
  1455.     lea        CurChar(a2),a0    ; pass pointer
  1456.     move.w        d4,(a0)        ; set value at ptr
  1457.     clr.w        d0            ; pass length
  1458.     sub.l        #2,SP            ; allocate return
  1459.     move.l        a0,-(sp)        ; pointer
  1460.     move.w        d0,-(sp)        ; offset
  1461.     _CharByte
  1462.     tst.w    (sp)+            ; test return
  1463.     bmi.s    @DoubleByte        ; skip if high byte (first two) 
  1464. ; we don’t have a double byte, but two special cases combine second bytes
  1465.     move.b    (a3),d0             ; get next byte
  1466.     cmp.b    #$DE,d0            ; nigori?
  1467.     beq.s    @DoubleByte            ; add in
  1468.     cmp.b    #$DF,d0            ; maru?
  1469.     bne.s    ReturnEq            ; exit: single byte
  1470. @DoubleByte
  1471.     move.b    (a3)+,d4            ; get next byte
  1472.     subq.w    #1,StrCnt(A2)            ; dec string length
  1473.     addx.w    d5,d5                ; set x=1 if string len = 0
  1474.     rts                    ; return to caller with CCR=NE
  1475. The Project Procedure
  1476. The Project Procedure is used to find the primary ordering for a character. This routine will map characters that differ only in the secondary ordering onto a single character, typically the unmodified, uppercase character. For example, the following changes the comparison order for some Norwegian characters, so that they occur after ‘Z.’
  1477. ;------------------------------------------------------------------------
  1478. ; Routine    ProjectProc
  1479. ; Input    A2          String Data Structure
  1480. ;        D4.W        Character (top byte is char, bottom is extension
  1481. ;                    (the extension is zero unless set by FetchProc))
  1482. ; Output    D4.W        Projected Character
  1483. ;        CCR         NE to skip normal Project
  1484. ; Trashes    Standard regs:    A0/A1/D0-D2
  1485. ; Function    This routine projects the secondary characters onto primary
  1486. ;                  characters.
  1487. ;        Example: a,ä,Ä -> A
  1488. ;------------------------------------------------------------------------
  1489. ProjectProc
  1490.     lea    ProjTable,A1    ; load table address.
  1491. @findChar
  1492.     move.l    (a1)+,D0        ; get entry
  1493.     cmp.w    d0,d4            ; original ≥ entry?
  1494.     bhi.s    @findChar        ; no, try the next entry.
  1495.     bne.s    ReturnEq        ; not equal, process normally
  1496. @replaceChar
  1497.     swap    d0            ; get replacement
  1498.     move.w    d0,d4            ; set new character word.
  1499. @doneChar
  1500.     rts                ; CCR is NE to skip project.
  1501.     
  1502. ProjTable
  1503. ;    Table contains entries of the form  r1, r2, o1, o2,
  1504. ;    where r1,r2 are the replacement word, and 
  1505. ;    o1, o2 are the original character.
  1506. ;    The entries are sorted by o1,o2 for use in the above algorithm
  1507.     DC.B    'Z', 3, 'Å', 0    ; Å after Ø
  1508.     DC.B    'Z', 3, 'å', 0    ; å after Ø
  1509.     DC.B    'Z', 1, 'Æ', 0    ; Æ after Z
  1510.     DC.B    'Z', 2, 'Ø', 0    ; Ø after Æ
  1511.     DC.B    'Z', 1, 'æ', 0    ; æ after Z
  1512.     DC.B    'Z', 2, 'ø', 0    ; ø after Æ
  1513.     DC.L    $FFFFFFFF        ; table end
  1514. The Project procedure can also be used to undo the effects of the normal projection. For example, suppose that “œ” is not to be expanded into “oe”: in that case, a simple test can be made against 'œ',0, returning NE if there is a match, so that the normal processing is not done. To expand one character into two, the routine should return the first replacement character in D4.W, and modify two fields in the IUStrData field. For example, given that A1 points to a table entry of the form (primaryCharacter: Word; secondaryCharacters: Word), the following code could be used:
  1515.     …
  1516.     move.w    (a1)+,d4        ; return first, primary character
  1517.     move.w    (a1)+,CurChar(A2)    ; original => first, modified char.
  1518.     addq.b    #1,JustAfter(A2)    ; set to one (otherwise zero)
  1519.     move.b    (a1),BufChar(A2)    ; store second character (BYTE!)
  1520.     …
  1521. CurChar is where the original character returned by FetchChar is stored. If characters are different even after being projected onto their respective primary characters, then the CurChar values for each string will be compared. JustAfter indicates that the expanded character should sort after the corresponding unexpanded form. This field must be set whenever CurChar is modified in order for the comparison to be fully ordered. BufChar stores the next byte to be retrieved from the string by FetchChar.
  1522. To handle the case where characters are ignored unless the two compared strings are otherwise equal, the IgnChar flag can be set. This can be used to handle characters such as the hyphen in English, or vowels in Arabic.
  1523.     …
  1524.     cmp.w    #hyphen,d0        ; is it a ignorable?
  1525.     seq    IgnChar(a2)        ; set whether or not
  1526.     …
  1527. The Vernier Procedure
  1528. The Vernier Procedure is used to make a final comparison among characters that have the same primary ordering. It is only needed if the CurChar values are not ordered properly. For example, according to the binary encoding, å < Ã. To change this ordering so that uppercase letters are before lowercase letters, Ã is mapped to $7F in normal comparison. Notice that only the characters in the secondary ordering are affected: Ã can be mapped onto Z, but not onto Ä, since that would cause a collision.
  1529. ;------------------------------------------------------------------------
  1530. ; Routine    VernierProc
  1531. ; Input    D4.B                High byte of character
  1532. ;        D5.B            Low byte of character
  1533. ; Output    D4.B            High byte of character
  1534. ;        D5.B            Low byte of character
  1535. ;        CCR             NE if to skip standard Vernier
  1536. ; Trashes    Standard regs:    A0/A1/D0-D2
  1537. ; Function    The Vernier routine compares characters within the secondary
  1538. ;                      ordering if two strings are otherwise equal.
  1539. ;                      Example: (a,A,Ä,ä)
  1540. ;------------------------------------------------------------------------
  1541. VernierProc    
  1542.     not.b        d4        ; invert secondary ordering
  1543.     not.b        d5        ; ditto for lower byte
  1544.     bra.s        ReturnEq    ; normal processing afterwards
  1545. Installing an itl2 resource 
  1546. To write an itl2 resource, follow the guidelines in M.PT.StandAloneCode for writing standalone code in MPW. The code should be written in assembly language, and it must follow the specifications given in this technical note or serious system errors could occur whenever string comparisons are made.
  1547. The default comparison routine is in the itl2 resource of the System file. In order to use a comparison routine other than the standard one, you should include an itl2 resource in your application with the same name and resource ID as the one in the System file that you wish to change. The Resource Manager will look for the resource in the application resource file before it looks in the System resource file, so your string comparison routine will be used instead of the default one.
  1548. It is generally a dangerous practice to change a system resource since other applications may depend on it, but if you have good reasons to permanently change the system itl2 resource so that all applications use a different comparison routine, then you should write an installer script to change the itl2 resource in the System resource file. Writing an installer script is documented in M.TP.Installer. You are required to write an installer script if you are planning to ship your application on a licensed system software disk and your application makes a permanent change to any resources in the System file. We strongly discourage changing the System itl2 as that would change the behavior of string comparison and sorting for all applications. If that is your intent, then you should write an installer script. However, if you are changing the itl2 resource in the System file for academic or internal use, then you can use a resource editor such as ResEdit to copy your itl2 resource into the System file.
  1549. Further Reference:
  1550. •    The International Utilities
  1551. •    M.TP.Installer
  1552. •    M.PT.StandAloneCode
  1553. Styled TextEdit Changes in System 6.0
  1554. Text        M.TE.TextEditChanges
  1555. Revised by:    Chris Derossi    December 1988
  1556. Written by:    Chris Derossi    August 1988
  1557. Some changes were made to TextEdit in System 6.0 to provide more functionality and to make life easier for the programmer using TextEdit.  This Note documents those changes and enhancements.
  1558. Changes since August  1988:  Corrected an error in TEDispatchRec in the figure on page 8.
  1559. TextEdit Changes
  1560. In order to improve the usability of styled TextEdit, some routines have been changed, and some new routines have been added.  These changes exist in System Software 6.0 and later.  If you intend to rely on any of these changes or new routines, it is important that you call _SysEnvirons first to make sure you are running under System Software 6.0 or later.
  1561. _SysEnvirons is documented in Inside Macintosh, Volume V and M.OV.GestaltSysenvirons.  To check for the styled TextEdit changes, you might do the following:
  1562.     VAR
  1563.         theWorld:    SysEnvRec;
  1564.         anErr    :    OSErr;
  1565.     BEGIN
  1566.         anErr := SysEnvirons(1, theWorld);
  1567.         IF (anErr = noErr) AND (theWorld.systemVersion >= $0600) THEN … 
  1568.             {System 6.0 or later}
  1569.     END;
  1570. Changes to Existing Routines
  1571. _TEKey and _TEDelete have been changed so that backspacing to the beginning of a style no longer deletes that style.  Instead, the style is saved in the nullScrap to be applied to subsequently typed characters.  As soon as the user has backspaced past the beginning of the style, or clicked in some other area of the text, the style is removed.
  1572. GetStylScrap now returns a handle to a valid style scrap record when called for an insertion point (selStart = selEnd).  NIL is still returned when GetStylScrap is called with an old style TEHandle.
  1573. TESetStyle now accepts an additional mode, doToggle (= 32).  When doToggle is specified along with doFace, TESetStyle operates as follows:  If a style specified in the given TextStyle parameter exists across the entire selected range, that style is removed (turned off).  Otherwise, all of the selected text is set to include that style.  When a particular style is set for an entire selection range, that style is said to be continuous over the selection.
  1574. For example, given that the following text is the current selection:
  1575. then the style bold is continuous over the selection range and the italic style is not.  If TESetStyle were called with a mode of doFace + doToggle and a TextStyle tsFace field of [bold], then the resulting selection would be:
  1576. On the other hand, if TESetStyle had been called with a mode of doFace + doToggle and a TextStyle tsFace field of [italic], then the selected text would have become:
  1577. New TextEdit Routines 
  1578. Some new routines have been added to TextEdit, TEContinuousStyle, SetStylScrap, TECustomHook, and TENumStyles.  These routines are described in detail below.
  1579. Assembly language note:
  1580. The new TextEdit routines are called via the _TEDispatch trap.  Following are the decimal selectors for the new routines:
  1581.     TEContinuousStyle    10
  1582.     SetStylScrap    11
  1583.     TECustomHook    12
  1584.     TENumStyles    13
  1585. TEContinuousStyle 
  1586. FUNCTION TEContinuousStyle(VAR mode : Integer; VAR aStyle : TextStyle;
  1587.                        hTE : TEHandle) : Boolean;
  1588. TEContinuousStyle gives you information about the attributes of the current selection.  The mode parameter, which takes the same values as in TESetStyle, specifies which attributes should be checked.  When TEContinuousStyle returns, the mode parameter indicates which of the checked attributes is continuous over the selection range and the aStyle parameter is set  to reflect the continuous attributes.
  1589. TEContinuousStyle returns TRUE if all of the attributes to be checked are continuous and FALSE if not.  In other words, if the mode parameter is the same before and after the call, then TEContinuousStyle returns TRUE.
  1590. For example, TEContinuousStyle is useful for marking the style menu items based on the current selection.
  1591.     mode := doFace;
  1592.     IF TEContinuousStyle(mode, aStyle, myTE) THEN BEGIN
  1593.     { There is at least one face that is continuous over the
  1594.       selection. Note that it might be plain which is actually
  1595.       the absence of all styles. }
  1596.         CheckItem(styleMenu, plainItem, aStyle.tsFace = []);
  1597.         CheckItem(styleMenu, boldItem, bold IN aStyle.tsFace);
  1598.         CheckItem(styleMenu, italicItem, italic IN aStyle.tsFace);
  1599.         ...etc.
  1600.     END ELSE BEGIN
  1601.     { No text face is common to the entire selection. }
  1602.         CheckItem(styleMenu, plainItem, FALSE);
  1603.         CheckItem(styleMenu, boldItem, FALSE);
  1604.         CheckItem(styleMenu, italicItem, FALSE);
  1605.         ...etc.
  1606.     END;
  1607. This function can also be used to determine the actual values for those attributes that are continuous for the selection.  Note that a field in the TextStyle record is only valid if the corresponding bit is set in the mode variable; otherwise the field contains garbage.  For example, to determine the font, face, size, and color of the current selection:
  1608.     mode := doFont + doFace + doSize + doColor;
  1609.     continuous := TEContinuousStyle(mode, aStyle, myTE);
  1610.     IF BitAnd(mode, doFont) <> 0 THEN
  1611.         { Font for selection = aStyle.tsFont. }
  1612.     ELSE
  1613.         { More than one font in selection. };
  1614.     IF BitAnd(mode, doFace) <> 0 THEN
  1615.         { aStyle.tsFace contains the text faces (or plain) that are
  1616.           common to the selection. }
  1617.     ELSE
  1618.         { No text face is common to the entire selection. };
  1619.     IF BitAnd(mode, doSize) <> 0 THEN
  1620.         { Size for selection = aStyle.tsSize. }
  1621.     ELSE
  1622.         { More than one size in selection. };
  1623.     IF BitAnd(mode, doColor) <> 0 THEN
  1624.         { Color for selection = aStyle.tsColor. }
  1625.     ELSE
  1626.         { More than one color in selection. };
  1627. The aStyle.tsFace field is a bit tricky.  When TEContinuousStyle returns a mode that contains doFace, and an aStyle.tsFace field that contains [bold, italic], it means that the selected text is all bold and all italic, but may contain other text faces as well.  None of the other faces will apply to all of the selected text, or they would have been included in the tsFace field.  But if the tsFace field is the empty set ([] = plain), then all of the selected text is plain.
  1628. If the current selection range is an insertion point, TEContinuousStyle returns the style information for the next character to be typed.  TEContinuousStyle will always return TRUE in this case, and each field of the TextStyle record will be set if the corresponding bit in the mode parameter was set.
  1629. SetStylScrap
  1630.     PROCEDURE SetStylScrap(rangeStart, rangeEnd : LongInt;
  1631.                      newStyles : StScrpHandle; hTE : TEHandle);
  1632. SetStylScrap performs the opposite function of GetStylScrap.  The newStyles parameter is a handle to a style scrap record which will be applied over the given range of text.  The current selection range is not changed.  If newStyles is NIL or hTE is a handle to an old style TERecord, SetStylScrap does nothing.
  1633. SetStylScrap will terminate without error if it prematurely reaches the end of the range or if there are not enough scrap style elements to cover the whole range.  In the latter case, the last style in the scrap record will be applied to the remainder of the range.
  1634. TENumStyles
  1635.     FUNCTION TENumStyles(rangeStart, rangeEnd : LongInt;
  1636.                    hTE : TEHandle) : LongInt;
  1637. This function returns the number of style changes contained in the given range, counting one for the start of the range.  Note that this does not necessarily represent the number of unique styles for the range, because some styles may be repeated.  For old-style TextEdit records, this function always returns 1.
  1638. This function is useful for calculating the amount of memory that would be required for a contemplated _TECut or _TECopy.  Since the style scrap record is linear in nature, with one element for each style change, you can multiply the result returned by TENumStyles by SizeOf(ScrpSTElement) and add 2 to get the amount of memory that will be needed.
  1639. TECustomHook
  1640.     PROCEDURE TECustomHook(which : TEHook; VAR addr : ProcPtr;
  1641.                      hTE : TEHandle);
  1642. This procedure lets applications customize the functions of TextEdit by setting the TextEdit bottleneck routines.  The which parameter specifies which bottleneck routine to replace, and is of type TEHook (described below).  When TECustomHook returns, the addr parameter contains the address of the previous bottleneck routine specified by which.  This is returned so that bottleneck routines can be daisy-chained.
  1643.     TYPE
  1644.         TEHook = (intEOLHook, intDrawHook, intWidthHook, intHitTestHook);
  1645. The internally used fields, recalBack and recalLines now form a handle to the list of TextEdit bottleneck routines.  Each TERecord has its own set of bottleneck routines to provide for maximum flexibility.  The TECustomHook procedure should always be used to change the bottleneck routines instead of modifying the edit record directly.
  1646. Also, it is important to note that you should not clone a TERec.  Doing so would duplicate the handle stored in recalBack and recalLines.  When one of the TextEdit records was disposed, the handle stored in the copy would be invalid, and TextEdit would crash.
  1647. There are four bottleneck routines, TEEOLHook, TEWidthHook, TEDrawHook, and TEHitTestHook, described individually below.  When replacing these routines, note that all registers except those specified as containing return values must be preserved.  Registers A3 and A4 contain a pointer and a handle to the TextEdit record respectively.  Line start positions can be obtained from the lineStarts array in the edit record.
  1648. None of these bottleneck routines are called from _TextBox.
  1649. TEEOLHook
  1650. This routine tests a given character and returns with the appropriate status flags set in the status register.  The default action is to merely compare the character with $0D (a carriage return) and return.
  1651. On entry:    D0    character to compare            (byte)
  1652.         A3    pointer to the TextEdit record        (long)
  1653.         A4    handle to the TextEdit record        (long)
  1654. On exit:        z flag clear if end-of-line character, set otherwise
  1655. TEWidthHook
  1656. This routine is called any time the width of various components of a line are calculated.  The appropriate font, face, and size characteristics have already been set into the current port by the time this routine is called.  The default action is to call _Char2Pixel and return.
  1657. On entry:    D0    length of text to measure        (word)
  1658.         D1    offset into text            (word)
  1659.         A0    pointer to text to measure        (long)
  1660.         A3    pointer to the TextEdit record        (long)
  1661.         A4    handle to the TextEdit record        (long)
  1662. On exit:    D1    width of measured text        (word)
  1663. TEDrawHook
  1664. This routine is called any time the various components of a line are drawn.  The appropriate font, face, and size characteristics have already been set into the current port by the time this routine is called.  The default action is to call _DrawText and return.
  1665. On entry:    D0    offset into text            (word)
  1666.         D1    length of text to draw            (word)
  1667.         A0    pointer to text to draw        (long)
  1668.         A3    pointer to the TextEdit record        (long)
  1669.         A4    handle to the TextEdit record        (long)
  1670. TEHitTestHook
  1671. This routine is called to determine the character position in a line given the horizontal offset, in pixels, from the beginning of a line.  The default action is to call _Pixel2Char and return.  For more information, see the description of _Pixel2Char in the Script Manager chapter of Inside Macintosh, Volume 5 and the Inside Macintosh Interim Chapter Draft, Script Manager 2.0.
  1672. On entry:    D0    length of text to hit test        (word)
  1673.         D1    pixel offset from start of text        (word)
  1674.         A0    pointer to start of text            (long)
  1675.         A3    pointer to the TextEdit record        (long)
  1676.         A4    handle to the TextEdit record        (long)
  1677. On exit:    D0    pixel width to last offset        (low word)
  1678.             Boolean = TRUE if a character    (high word)
  1679.             offset corresponding to the pixel width was found.
  1680.         D1    character offset            (word)
  1681.         D2    Boolean = TRUE if the pixel        (word)
  1682.             offset falls within the left side of the character.
  1683. TextEdit Data Structures
  1684. The illustration on the following page is a graphic representation of the TextEdit data structures.  You should use this information only for debugging and so you understand what is going on.  For reading or writing these data structures, the TextEdit routines should be used. This will help ensure future compatibility.
  1685. Further Reference:
  1686. •    M.OV.GestaltSysenvirons
  1687. TEScroll Bug
  1688. Text        M.TE.TEScrollBug
  1689. Revised by:        March 1988
  1690. Written by:    Bryan Stearns    April 1986
  1691. A bug in TextEdit causes the following problem: a call to TEScroll with no horizontal or vertical displacement (that is, both dh and dv set to zero) results in disappearance of the insertion point. Since such calls do nothing, they should be avoided:
  1692.     IF (dh <> 0) OR (dv <> 0) THEN TEScroll(dh,dv,myTEHandle);
  1693. Further Reference:
  1694. •    TextEdit
  1695. •    M.TE.TextEditBugs
  1696. TextEdit: Advice & Descent
  1697. Text        M.TE.TextEditAdvice
  1698. Revised by:        March 1988
  1699. Written by:    Rick Blair    June 1986
  1700. This technical note will point out some bugs (and possible workarounds), and other items of interest for the TextEdit programmer.
  1701. TESelRect
  1702. Multiple line selections are often more complex shapes than simple rectangles. If this is the case, the teSelRect field of the TERec is set to the last (bottommost) rectangle in the selection. The teHiHook is called to invert each line of the selection.
  1703. The ROM limits the selection range (i.e. the lines that get set into teSelRect) to only those lines which will fit into the viewRect. This means that teSelRect will be left at the last visible line. (The old 64K ROMs made all the calls for the complete selection and just let clipping take care of the rest.)
  1704. TEDoText
  1705. The parameters of this special hook into TextEdit need a little additional explanation. D3 and D4 are described on page 391 of Inside Macintosh Volume I as being the first and last characters to be redrawn. This is true but specific to the –1 “DoDraw” case. In fact, all the calls to TEDoText are interested in these first and last character positions. They determine the selection for a (1) highlight call, the caret position for a (–2) DoCaret call (where D4 is ignored as it’s assumed to equal D3), etc.
  1706. Note that the DoCaret (–2) call behaves differently than described in Inside Macintosh, as well. Good old page 391 says it sets up the pen position for caret drawing. Since an InvertRect call is used to draw the caret if you use the default teCarHook, the ROMs just set up teSelRect, they don’t bother with the QuickDraw pen.
  1707. TEScrpLength
  1708. Inside Macintosh describes TEScrpLength as a long integer; indeed, four bytes are reserved for this value with the intent of someday using that range of values. However, the ROMs use word operations in their accesses to TEScrpLength and make word calculations with it. This means that the high word of TEScrpLength is used for calculations. This is something to watch out for.
  1709. CharWidth
  1710. Inside Macintosh says that CharWidth takes stylistic variations into account when determining the width of a character. In fact, for italic and outlined styles the extra width is not taken into account. TextEdit relies on CharWidth for positioning of the caret, etc. If you have chosen to use, for instance, italic style in your TE record you will find that as you type the caret actually overlaps the character to the left and so when the caret is erased some of that character will get erased, too. This is somewhat disconcerting to the user but the program will still function correctly.
  1711. Clikloops
  1712. If you add your own click loop and try to do something like update scroll bars you may run into trouble. Before your routine gets called, TextEdit will have set clipping down to just the viewRect. You will have to save away the old clipping region, set it out to sufficient size (–32767, –32767, 32767, 32767 is probably OK), do your drawing, then restore TextEdit’s clipping area so that it can function properly.
  1713. Further Reference:
  1714. •    TextEdit
  1715. •    M.TE.TEScrollBug
  1716. •    M.TE.EOLAmbiguity
  1717. •    M.TE.TextEditBugs
  1718. TextEdit Bugs in System 4.2
  1719. Text        M.TE.TextEditBugs
  1720. Revised by:        March 1988
  1721. Written by:    Chris Derossi     June 1987
  1722. This note formerly described the known bugs with the version of Styled TextEdit that was provided with System 4.1. Many of these bugs were fixed in System 4.2. This updated Technical Note describes the remaining known problems.
  1723. TEStylInsert
  1724. Calling TEStylInsert while the TextEdit record is deactivated causes unpredictable results, so make sure to only call TEStylInsert when the TextEdit record is active.
  1725. TESetStyle
  1726. When using the doFace mode with TESetStyle, the style that you pass as a parameter is ORed into the style of the currently selected text. If you pass the empty set (no styles) though, TESetStyle is supposed to remove all styles from the selected text. But TESetStyle checks an entire word instead of just the high-order byte of the tsFace field. The style information is contained completely in the high-order byte, and the low-order byte may contain garbage.
  1727. If the low-order byte isn’t zero, TESetStyle thinks that the tsFace field isn’t empty, so it goes ahead and ORs it with the selected text’s style. Since the actual style portion of the tsFace field is zero, no change occurs with the text. If you want to have TESetStyle remove all styles from the text, you can explicitly set the tsFace field to zero like this:
  1728.     VAR
  1729.        myStyle  : TextStyle;
  1730.        anIntPtr : ^Integer;
  1731.     BEGIN
  1732.        ...
  1733.        anIntPtr := @myStyle.tsFace;
  1734.        anIntPtr^ := 0;
  1735.        TESetStyle(doFace, myStyle, TRUE, textH);
  1736.        ...
  1737.     END;
  1738. TEStylNew
  1739. The line heights array does not get initialized when TEStylNew is called. Because of this, the caret is initially drawn in a random height. This is easily solved by calling TECalText immediately after calling TEStylNew. Extra calls to TECalText don’t hurt anything anyway, so this will be compatible with future Systems.
  1740. An extra character run is placed at the beginning of the text which corresponds to the font, size, and style which were in the grafPort when TEStylNew was called. This can cause the line height for the first line to be too large. To avoid this, call TextSize with the desired text size before calling TEStylNew. If the text’s style information cannot be determined in advance, then call TextSize with a small value (like 9) before calling TEStylNew.
  1741. TEScroll
  1742. The bug documented in M.TE.TEScrollBug remains in the new TextEdit. TEScroll called with zero for both vertical and horizontal displacements causes the insertion point to disappear. The workaround is the same as before; check to make sure that dV and dH are not both zero before calling TEScroll.
  1743. Growing TextEdit Record
  1744. TextEdit is supposed to dynamically grow and shrink the LineStarts array in the TERec so that it has one entry per line. Instead, when lines are added, TextEdit expands the array without first checking to see if it’s already big enough. In addition, TextEdit never reduces the size of this array.
  1745. Because of this, the longer a particular TextEdit record is used, the larger it will get. This can be particularly nasty in programs that use a single TERec for many operations during the program’s execution. 
  1746. Restoring Saved TextEdit Records
  1747. Applications have used a technique for saving and restoring styled text which involves saving the contents of all of the TextEdit record handles. When restoring, TEStylNew is called and the TextEdit record’s handles are disposed. The saved handles are then loaded and put into the TextEdit record. This technique should not be used for the nullStyle handle in the style record.
  1748. Instead, when TEStylNew is called, the nullStyle handle from the style record should be copied into the saved style record. This will ensure that the fields in the null-style record point to valid data.
  1749. TextEdit Conversion Utility
  1750. Text        M.TE.TextEditConvert
  1751. Revised by:        March 1988
  1752. Written by:    Harvey Alcabes    April 1985
  1753. Text sometimes must be converted between a Pascal string and “pure” text in a handle. This note illustrates a way to do this using MPW Pascal.
  1754. Text contained in TextEdit records sometimes must be passed to routines which expect a Pascal string of type Str255 (a length byte followed by up to 255 characters). The following MPW Pascal unit can be used to convert between TextEdit records and Pascal strings:
  1755.     UNIT TEConvert;
  1756.        {General utilities for conversion between TextEdit and strings}
  1757.        INTERFACE
  1758.           USES MemTypes,QuickDraw,OSIntf,ToolIntf;
  1759.           PROCEDURE TERecToStr(hTE: TEHandle; VAR str: Str255);
  1760.           {TERecToStr converts the TextEdit record hTE to the string str.}
  1761.           {If necessary, the text will be truncated to 255 characters.}
  1762.           PROCEDURE StrToTERec(str: Str255; hTE: TEHandle);
  1763.           {StrToTERec converts the string str to the TextEdit record hTE. }
  1764.        IMPLEMENTATION
  1765.           PROCEDURE TERecToStr(hTE: TEHandle; VAR str: Str255);
  1766.              BEGIN
  1767.                 GetIText(hTE^^.hText, str);
  1768.              END;
  1769.           PROCEDURE StrToTERec(str: Str255; hTE: TEHandle);
  1770.              BEGIN
  1771.                 TESetText(POINTER(ORD4(@str) + 1), ORD4(length(str)), hTE);
  1772.              END;
  1773.     END.
  1774. Further Reference:
  1775. •    Macintosh Memory Management: An Introduction TextEdit
  1776. TextEdit EOL Ambiguity
  1777. Text        M.TE.EOLAmbiguity
  1778. Revised by:        March 1988
  1779. Written by:    Rick Blair     May 1987
  1780. TESetSelect may be used to position the insertion point at the end of a line. There is an ambiguity, though; should the insertion point appear at the end of the preceding line or the start of the following one? It is possible to determine what will happen, as you are about to see.
  1781. There is an internal flag used by TextEdit to determine where the insertion point at the end of a line appears. This flag is part of the clikStuff field in the TERec. It is there mainly for the use of TEClick, but it is also used by TESetSelect (although it defaults to the right side of the previous line).
  1782. The following code can be used to force the insertion point to appear at the left of the following line when it is positioned at the end of a line; in MPW Pascal:
  1783.     TEDeactivate(tH);
  1784.     tH^^.clikStuff := 255;            {position caret on left}
  1785.     TESetSelect(eolcharpos, eolcharpos, tH);    {ambiguous point}
  1786.     TEActivate(tH);
  1787. In MPW C:
  1788.     TEDeactivate(tH);
  1789.     (**tH).clikStuff = 255;            /*position caret on left*/
  1790.     TESetSelect(eolcharpos, eolcharpos, tH);    /*ambiguous point*/
  1791.     TEActivate(tH);
  1792. If you want to ensure that the caret is on the right side (to which it normally defaults) then substitute a zero for the 255.
  1793. Further Reference:
  1794. •    Inside Macintosh, Volume V, Compatibility Guidelines
  1795. •    M.OV.GestaltSysenvirons
  1796. TextEdit Record Size Limitations Revisited
  1797. Text        M.TE.RecordSizeLimit
  1798. Written by:    Mary Walsh    June 1989
  1799. This Technical Note describes another limit on the length of a TextEdit record that was previously undocumented.
  1800. The TextEdit chapters in Inside Macintosh document the 32K character limit on a TextEdit record length.  They do not, however, discuss the more subtle constraint on the size of the destRect.  By definition, the destRect uses integer values for the top-left and bottom-right boundary points.  It is possible to have values too large for the destRect without reaching the teLength limit.
  1801. The nLines field gives the number of lines in the edit record, and the lineHeight field specifies the vertical distance from the ascent line from one line of text to the ascent line of the next line.  In styled TextEdit, the lineHeight may vary for each line depending on the font and font size.  These values are entries in the lineHeight table.
  1802. Figure 1–LineHeight
  1803. The product of the lineHeight (or the largest lineHeight value in styled TextEdit) and nLines gives a good approximation, in pixels, of the vertical dimension of the destRect of the TERec used.  If this value is greater than 32,768, then unpredictable and erratic behavior may result.
  1804. For example:
  1805.     2,400 lines of Chicago 12 point yields nLines = 2,400 and lineHeight = 16. 
  1806.     nLines * lineHeight = 2400 * 16 = 38,400.  This is above the 32K limit.
  1807.     1,200 lines of Times 24 point yields nLines = 1,200 and lineHeight = 30.
  1808.     nLines * lineHeight = 1200 * 30 = 36,000.  This is above the 32K limit.
  1809. In both of the examples above, the number of characters in the edit record was less than 32,768.
  1810. Check All Constraints
  1811. Both TELength and the size of the destRect must be under the 32K limit.  You can compute an approximate vertical height of the destRect by finding the product of nLines and lineHeight (or the largest lineHeight value in styled TextEdit).
  1812. Further Reference:
  1813. •    Inside Macintosh, Volumes I-371 & V-259, TextEdit
  1814. •    M.OV.ManagerAbuse
  1815. TextEdit Q&As
  1816. Text        M.TX.TextEdit.Q&As
  1817. Revised by:    Developer Support Center    December 1992
  1818. Written by:    Developer Support Center    October 1990
  1819. This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
  1820. Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
  1821. New Q&As this month:
  1822. Extending TextEdit beyond 32K limit
  1823. Controlling TEIdle’s insertion point color
  1824. Extending TextEdit beyond 32K limit
  1825. Date written:    9/16/92
  1826. Last reviewed:    11/1/92
  1827. How do I get around the 32K limit in TextEdit? For example, if I have a 64K text file and I want to read it in and display it in a window, I can only read the first 32K. How do I make the text display smoothly when I need to read the next block of text in?
  1828. ___
  1829. Unfortunately, there’s no supported way of doing this. In the early days, TextEdit was designed for use primarily with the Dialog Manager, for displaying and editing small amounts of text at a time. Since then, many developers have used it, or wanted to use it for much more than it was intended. See the Technical Note “Don’t Abuse the Managers,” available on the Developer’s CD, (path: “Dev.CD Sept 92:Technical Documentation:Macintosh Technical Notes:Overview:Managerial Abuse”).
  1830. The Word Solution Engine by DataPak is a replacement for TextEdit that allows you to go beyond the 32K limit, as well as including many other features. Other packages are available as well. Check the Redgate Macintosh Directory on AppleLink or publications such as MacTutor magazine to find them.
  1831. Controlling TEIdle’s insertion point color
  1832. Date written:    7/6/92
  1833. Last reviewed:    11/1/92
  1834. Is it possible to control the color of the insertion point when I use TEIdle? If I have a light blue background color, the caret is always the invert of that background color and doesn’t have enough contrast to see it. I want to make the color of the caret black if possible.
  1835. ___
  1836. As is often the case, some of the seemingly simplest questions tend to yield the most interesting answers. Succinctly, your question stabs at the wobbly knees of QuickDraw’s color model. Sample code to change the color of the caret in a TextEdit record is in the Snippets folder. Here’s how to implement the color caret.
  1837. You can use the caretHook field of the TextEdit record (IM I-379). Basically, this procedure is called repeatedly by TEIdle to draw the caret. The function calls InvertRect each time. It draws the caret, and then it erases the caret. Unfortunately, this function needs to be implemented in assembly. So there are a few gotchas:
  1838. • The pointer to the rectangle for the caret is passed on the stack (not the whole rectangle).
  1839. • The function InvertRect becomes _InverRect in assembly.
  1840. • You can only use A4 for scratch (A0 and A1 are blown away by PaintRect), and then only if you saved and restore it.
  1841. • Make sure you pop off the rectangle pointer if you do not use it.
  1842. The default system function is simply _InverRect because the rectangle pointer is on the stack and _InverRect pops it off. For color, inverting is not the best idea, as you have noted. Inversion, if it isn’t black and white, does not give you the most contrast. Thus, we need another idea.
  1843. But, remember, we have a requirement to paint once, and then erase on the next pass. Inversion works nicely this way. To meet this requirement, use Xor mode with PaintRect. As you know, Xor mode is “or” mode with the double 1s being set to 0 instead of 1. This trait is ideal in your situation because, always having the same caret pattern, drawing a second time obliterates the previous drawing of the caret. Thus, we get the blinking behavior. And, with the Macintosh II and Color QuickDraw, we get these cool things called pixel patterns (IM V-55). You can use your own pixel pattern as the pen pattern, bring it in from the resource, and then use PaintRect in the patXor mode to achieve the desired effect. Done, right? 
  1844. Unfortunately, here we run into a major flaw of QuickDraw: It is based on two color models, indexed and direct. And, arithmetic operations are performed on the pixel values, and not the colors. In the indexed model, a pixel value of 0x00 is white. (The pixel value in the indexed color model is really an index into a color table.) If you Xor it with 0xFF, you’ll get 0xFF, or black. If you Xor 0xFF with 0xFF, you’ll get 0x00 or white again. On the other hand (in the direct color model), a pixel value of 0x00 is black. If you Xor it with 0xFF, you’ll get 0xFF, or white. This is a problem.
  1845. So, you’ll need to perform conditional caret coloring (sounds like a disease). Depending on the depth, you’ll need to use a different pixel pattern. One good way is to use DeviceLoop (Inside Macintosh Volume VI, page 21-23). Though it’s included with System 7.0, there’s a simulated one as described in the article “Multiple Screens Revealed” on page 57 of develop #10. DeviceLoop lets you provide a routine that is called for each screen that the drawing area touches. In this case, the drawing routine is your PaintRect routine for the caret. This drawing routine gets passed the depth of the screen. So, based on the depth of the screen, you can use a different pixel pattern to draw with. For pixel depth of 32 or direct color mode, you can use one pattern, and for the rest you can use a different pattern.
  1846. Note, the drawing routine used by DeviceLoop allows you to pass in a LONGINT of userdata. With this longint, you can pass in the pointer to the rectangle from the assembly routine.
  1847. Resizing a Macintosh edit field for TEPaste
  1848. Written:    11/27/91
  1849. Last reviewed:    11/27/91
  1850. I have a small edit field and when I call TEPaste, the edit field contents scroll up. How can I calculate what the height of the edit field would be after the paste, resize the edit field to be that size, and then do the paste?
  1851. ___
  1852. There are a couple of ways to implement this:
  1853. Method #1:
  1854. 1. Set the clip region to something other than the viewRect of the edit field. 
  1855. 2. Call TEPaste or TEStylPaste to insert the clipboard text.
  1856. 3. Call TEGetHeight to get the new height of the text.
  1857. 4. Set the viewRect of the TERec to the new height. Call TECalText for good measure (and good lineStarts).
  1858. 5. Finally, set the clip region back to normal and call TEUpdate.
  1859. Method #2:
  1860. 1. Call TENew or TEStylNew to allocate a brand spankin’ new temporary TERec, and give it a viewRect and destRect that’s off the screen but that has the same width as the original TERec.
  1861. 2. Next, copy the hText handle of the window’s TERec into the hText field of the temporary TERec (good job for BlockMove [IM II-44]).
  1862. 3. Call TECalText and TEActivate on it; then paste the clipboard text into the temporary TERec. Since the view and dest Rects are off the screen, none of this will be seen by the user.
  1863. 4. Call TEGetHeight to get the new height, then copy the text back into the original TERec.
  1864. 5. Finally, call TECalText, then TEUpdate and TEActivate on the original TERec.
  1865. Method #1 has less overhead and is a little easier to implement. However, if you have any custom hooks installed in your TERec, then you probably want to let TextEdit do as much of the work as possible. In this case, method #2 is a better way.
  1866. Saving and restoring styled Macintosh TextEdit records
  1867. Written:    11/26/90
  1868. Last reviewed:    12/19/90
  1869. How do I save and restore Macintosh records created with TextEdit that contain styles? Where can I find additional information or sample code?
  1870. ___
  1871. There’s no standard for saving text with styles created by TextEdit, so all we can offer is a recommendation that’s modeled after the way that TECopy works on styled text. In styled TextEdit, the style information is stored separately from the text rather than embedded within it. TECopy maintains this separation when styled text is copied, so our recommendation maintains this separation, too.
  1872. To save the text part, you could make a file of type TEXT and save the text in the data fork of the file, like TeachText does. You could also save it in a resource of type TEXT.
  1873. The best way to save the style information is to use the StScrpRec record. Other records used by styled TextEdit contain references to other structures or they contain only a part of the style information, and that makes saving them awkward. The StScrpRec doesn’t contain references to any other structures, and it contains enough information to rebuild the entire tree of TextEdit structures. When you call TECopy on styled text, both a 'TEXT' and 'styl' scrap type is placed into the desk scrap. The 'TEXT' type just contains the text. The 'styl' type contains a StScrpRec containing all of the style information for the copied text. TextEdit doesn’t maintain a StScrpRec for the entire text buffer, so you have to tell TextEdit to do this for you when you’re ready to save the style information.
  1874. Fortunately, one call does it all. Inside Macintosh Volume V, page 268, documents the GetStylScrap routine. It creates a new StScrpRec record, places all the style information of the selected text into it, and returns a handle to this StScrpRec. First, select the text you want to save either by calling TESetSelect or by setting the selStart and selEnd fields of the TextEdit record if you don’t want the selection to be visible to the user. (If you do this, remember to restore the old values of selStart and selEnd after you get the StScrpHandle.) Next, call GetStylScrap to construct the StScrpRec. You can now save the resulting StScrpRec, perhaps in a resource of type 'styl' or in whatever way you see fit.
  1875. Reading the text and styles back into a TextEdit record isn’t much more complicated. First, read the text back into a buffer and read the 'styl' resource (or however you saved it) into a StScrpRec. Create a styled TextEdit record (or use an old one), then call TEStylInsert, passing it a pointer to the text buffer and a handle to the StScrpRec. Your TextEdit record should then contain and display your original styled text. That’s all! 
  1876. Macintosh SetClikLoop procedure and TERec clikLoop field
  1877. Written:    7/30/91
  1878. Last reviewed:    8/1/91
  1879. I have had some problems with the SetClikLoop procedure that don’t appear when I set the clikLoop field directly (in C). Why does TextEdit’s SetClikLoop procedure create a special procedure to call my clikLoop routine, rather that just installing the clikLoop directly? Inside Macintosh says you can set the clikLoop field directly in assembly. Why not in C?
  1880. ___
  1881. The short answer is that the special procedure is a glue routine for shuttling a result between the stack and the register D0. The larger question is why does installing clikLoop directly work? C, I think, is the culprit.
  1882. But, before I get ahead of myself, let me explain the SetClikLoop procedure. As you know, the click loop routine has no parameters but it does return a Boolean result (IM I-380).
  1883. FUNCTION MyClikLoop : Boolean; { Pascal declaration }
  1884. pascal Boolean MyClikLoop();   { C declaration }
  1885. Now, MyClikLoop is called by the TextEdit Manager from inside the TEClick routine. The way the code was written, TEClick expects to get the Boolean result from D0. For assembly programmers, this is no problem. In Pascal, the return value is placed on the stack. So, D0 does not contain your routines’ Boolean and what TEClick grabs will be “who knows what” and your program should crash. SetClikLoop will install a glue routine that calls MyClikLoop. The glue routine will move the result from the stack to D0. By the way, this information is documented on pages 237–238 of Volume Two of Macintosh Revealed, Second Edition, by Stephen Chernicoff.
  1886. Now why is your program causing problems when you use SetClikLoop? You might have declared your MyClikLoop as a C function. Since MyClikLoop takes no parameters, nothing is put on the stack. But C, unlike Pascal, places its return value in D0. So, for C, the glue routine is not needed. On the other hand, if you use the SetClikLoop routine with a C routine, you will take the top 2 bytes off the stack and clobber D0 with the wrong answer. Thus, you might get problems.
  1887. Though the C routine may work by setting it directly to the clikLoop field, doing it that way is not the supported method. You should declare your MyClikLoop function as a Pascal function and use SetClikLoop.
  1888. Special handling for Control-P keyboard input in a Mac dialog
  1889. Written:    6/5/91
  1890. Last reviewed:    8/1/91
  1891. Under System 6, when Control-P is pressed, a DLE character (hex 10) appears in a Macintosh dialog’s editText field. Under System 7, pressing Control-P produces no change in the editText box. The character is fed in via a normal (unaltered) keyDown event fed to DialogSelect. Does Control-P have some special meaning to DialogSelect or TextEdit now?
  1892. ___
  1893. Believe it or not, and it took several of us scratching our heads to figure this out; yes, it does, and this is by design! What you are running into is the Dialog Manager and TextEdit working together to make Cut, Copy, and Paste function keys work on an extended keyboard. The function keys on the top of an extended keyboard return $10 as their ASCII keycode. Thus, when TEKey detects that it is being called from dialog select, and the key you pass is a $10, it then looks for the event record on the stack and gets the raw keycode to determine which edit operation to perform. The bottom line is that it will not then enter the $10 in the edit field.
  1894. There is a simple workaround, and that is to install a filter proc in your dialog that detects keystrokes (actually it could always just look for this certain keystroke) and passes them to TEKey itself, thus skirting the whole issue.
  1895. Dimming and disabling a specific TEditText object
  1896. Written:    8/8/91
  1897. Last reviewed:    8/13/91
  1898. How can I dim and disable a specific TEditText object in my TDialogView so the field is not editable? 
  1899. ___
  1900. The trick is to use the TView methods Dimstate and ViewEnable to disable and dim the TEditText Views, and then do a TEditText.StopEdit (which disables editing in the TEditText box), and in the other case enable dimming and the view itself and use the TEditText.StartEdit (which enables editing in the TEditText box), as shown in the C++ example below:
  1901.             anEditText2->DimState(TRUE,kDontRedraw);        // disable
  1902.             anEditText2->ViewEnable(FALSE,kRedraw);
  1903.             anEditText2->StopEdit();
  1904.            
  1905.             anEditText1->DimState(FALSE,kDontRedraw);        // enable
  1906.             anEditText1->ViewEnable(TRUE,kRedraw);
  1907.             anEditText1->StartEdit(TRUE,fTEView);
  1908. MacApp sample code using this technique is included with DTS’s Snippets files.
  1909. Get TEHandle from DialogPeek, not GetDItem
  1910. Written:    1/17/92
  1911. Last reviewed:    2/17/92
  1912. I want to show all characters in my Macintosh control panel as bullets where the password is typed in. I cannot get the TECustomHook to work properly, it crashes before it gets to my hook routine. In the following Think C example, CPtr is dereferenced from the handle used in the control panel’s cdevValue field:
  1913.    GetDItem(DPtr, ADMINPWTE+NumItems, &theType, &theItem, &theRect);
  1914.    CPtr->myTEProc = (ProcPtr)TEPWHook;
  1915.    TECustomHook(intDrawHook, &CPtr->myTEProc, theItem);
  1916. ___
  1917. GetDItem does NOT return a TEHandle; it returns a handle to the current text of the edit item. You must get TEHandle from DialogPeek and must always monitor and change the TECustomHook on the fly. There is only one TEHandle for a dialog, no matter how many edit items are associated with the dialog. See the description of the DialogRecord data type in Inside Macintosh.
  1918. Cursor flicker while using Macintosh TextEditWritten:    5/6/92
  1919. Last reviewed:    9/15/92
  1920. The cursor flashes when the user types in TextEdit fields in my Macintosh application. This is done in TEKey. I notice that most programs hide the cursor once a key is pressed. I don’t care for this because then I have to move the mouse to see where I am. Is this a typical fix for this problem and an accepted practice?
  1921. ___
  1922. There’s very little you can do to avoid this. The problem is that every time you draw anything to the screen, if the cursor’s position intersects the rectangle of the drawing being done, QuickDraw hides the cursor while it does the drawing, and then shows it again to keep it from affecting the image being drawn beneath it. Every time you enter a character in TextEdit, the nearby characters are redrawn. Usually this is invisible because the characters just line up on top of their old images, but if the cursor is nearby and visible, it will flicker while it’s hidden to draw the text. This is why virtually all programs call ObscureCursor when the user types. Also, most users don’t want the image of the cursor obscuring text they might be referring to, yet they don’t want to have to move it away and then move it back to make selections. Because it’s so commonplace, hiding the cursor probably won’t bother your users; in fact, they might very well prefer the cursor hidden. This, combined with the fact that there’s very little you can do to help the flickering, suggests that you should obscure the cursor while the user types.
  1923. TextEdit Technicalities
  1924. Text        M.TE.TextEditTech
  1925. Revised by:    Mary Burke    April 1990
  1926. Written by:    Mary Burke    February 1990
  1927. This Technical Note discusses some areas in TextEdit that have not previously been clearly documented.
  1928. Changes since February 1990:  Added a note about the changes in TextEdit for System Software 6.0.5, documented the low-memory global TESysJust, clarified information about text direction and _TESetJust, discussed problems with the SetWordBreak routine along with a solution to work around it, and described the differences in dialog text item behavior.
  1929. TextEdit in 6.0.5
  1930. In addition to all the features of earlier versions, TextEdit 3.0 now allows you to take advantage of the Script Manager’s handling of systems with more than one script system installed.  TextEdit uses the Script Manager to support such systems and now exhibits the correct behavior for editing and displaying text in multiple styles and different scripts.  Multiple scripts can even exist on a single line due to TextEdit’s use of the Script Manager.  The new version of TextEdit in 6.0.5:
  1931. •    handles mixed-directional text
  1932. •    synchronizes keyboards and fonts
  1933. •    handles double-byte characters
  1934. •    determines word boundaries and line breaks
  1935. •    provides outline highlighting in the background
  1936. •    buffers text for performance improvements
  1937. •    permits left justification in right-to-left directional scripts
  1938. •    customizes word breaking
  1939. •    customizes measuring
  1940. Refer to the TextEdit chapter in Inside Macintosh, Volume VI, for detailed documentation on TextEdit 3.0.
  1941. The LineStarts Array and nLines
  1942. The LineStarts array is a field in a TextEdit record that contains the offset position of the first character of each line.  This array has the following boundary conditions:
  1943. •    It is a zero-based array.
  1944. •    The last entry in the array must have the same value as teLength.
  1945. •    The maximum number of entries is 16,000.
  1946. To determine the length of a line you can use the information contained in the lineStarts array and nLines.  For example, if you want to determine the length of line n, subtract the value contained in entry n of the array from the value in the entry (n+1):
  1947.     lengthOfLineN := myTE^^.lineStarts[n+1] - myTE^^.lineStarts[n];
  1948. The terminating condition for this measurement is when n = nLines + 1.  It is important not to change the information contained in the array.
  1949. TESysJust
  1950. TESysJust is a low-memory global that specifies the system justification.  The default value of this global is normally based on the system script.  It is -1 when a system’s default line direction is right to left, and 0 for a default left-to-right line direction.  Applications may change the value using the Script Manager routine SetSysJust; however, these applications should save the current value before using it and restore it before exiting the application or processing a MultiFinder suspend event.  The current value may be obtained using the Script Manager routine GetSysJust.
  1951. Forcing Text Direction
  1952. The original TextEdit documentation introduced _TESetJust with three possible choices for justification:  teJustLeft (0), teJustCenter (1), and teJustRight (-1).  These choices are appropriate for script systems that are read from left to right.  However, in script systems that are read from right to left, text is incorrectly displayed as left justified in dialog boxes and in other areas of applications where users cannot explicitly set the justification.  To fix this problem, the behavior of teJustLeft has changed to match the line direction of the system in use, which is the value stored in TESysJust.  Another constant has been added to allow an application to force left justification:  teForceLeft (-2).  This constant has been available for some time, but it has not been documented until now.  If your application does not allow the user to change the justification, then it should use teJustLeft; if it does, then it should use teForceLeft for left justification.
  1953. A Little More on Redraw in _TESetStyle
  1954. If the redraw parameter used in _TESetStyle is FALSE, line breaks, line heights, and line ascents are not recalculated.  Therefore a succeeding call to a routine using any of this information does not reflect the new style information.  For example, a call to _TEGetHeight (which returns a total height between two specified lines) uses the line height set previous to the _TESetStyle call.  A call to _TECalText is necessary to update this information.  If redraw is TRUE, the current style information is reflected. This behavior also holds for the redraw parameter in _TEReplaceStyle.
  1955. TEDispatchRec
  1956. There is currently space reserved for four documented hooks in the TEDispatchRec:  TEEolHook, TEWidthHook, TEDrawHook and TEHitTestHook.  The space beyond these hooks is reserved, and any attempt to use this private area results in corrupted TextEdit data.
  1957. Custom Word Breaks
  1958. A problem exists in one of TextEdit’s advanced procedures, SetWordBreak.  The current glue code does not preserve the state of the registers correctly; however, the solution is fairly simple.  Instead of calling SetWordBreak and passing a pointer to your custom word break routine, pass the pointer to your external glue which should call your custom word break routine.  Following is the glue code that correctly handles the registers:
  1959. WordBreakProc    PROC       EXPORT
  1960.                  IMPORT     MYWORDBREAK        ;Must be uppercase here
  1961.                  MOVEM.L    D1-D2/A1,-(SP)
  1962.                  CLR.W      -(SP)              ;Space for result
  1963.                  MOVE.L     A0,-(SP)           ;Move the ptr to stack
  1964.                  MOVE.W     D0,-(SP)           ;Move the charpos to Stack
  1965.                  JSR        MYWORDBREAK
  1966.                  MOVE.W     (SP)+,D0           ;Set Z bit
  1967.                  MOVEM.L    (SP)+,D1-D2/A1
  1968.                  RTS
  1969.                  ENDP
  1970. An external declaration is also necessary:
  1971.     FUNCTION WordBreakProc( text: Ptr; charPos: INTEGER ) : BOOLEAN; EXTERNAL;
  1972. as is the function itself.  One thing that should be noted is that it is not really necessary to have MyWordBreak boolean, but rather to have the Z bit set properly.  The result of the function should be zero when you do not want a break; otherwise, a non-zero value indicates a break is desired.
  1973.     FUNCTION MyWordBreak( text : Ptr; charPos : INTEGER ) : INTEGER;
  1974.     { Your word break code here. }
  1975. For more information, refer to the TextEdit chapter of Inside Macintosh, Volume I-380.
  1976. Static and Editable Text
  1977. The Dialog Manager depends on TextEdit to display text in dialog boxes.  For an editable text field, the Dialog Manager simply calls _TEUpdate.  Before making this call, it may double the width of the rectangle to contain the text if the height of the rectangle is sufficient for only one line and the line direction specified by TESysJust is left to right.  In this case, the Dialog Manager extends the rectangle on the right.  Note, however, this does not occur when your line direction is right to left.
  1978. For static text items, _TextBox is used instead.  When the display rectangle is not large enough. _TextBox clips the text to the size of the specified rectangle.  To avoid the clipping problem, simply make the display rectangle larger.  If your dialog box contains both static and editable text items, the difference in the text handling may appear inconsistent.
  1979. Further Reference:
  1980. •    Inside Macintosh, Volumes I,V & VI, TextEdit
  1981. •    Inside Macintosh, Volume V, The Script Manager
  1982. •    Inside Macintosh, Volume I, The Dialog Manager
  1983. •    M.TE.TestEditChanges
  1984. TrueType Q&As
  1985. Imaging    M.QD.TrueType.Q&As
  1986. Revised by:    Developer Support Center    October 1992
  1987. Written by:    Developer Support Center    October 1990
  1988. This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
  1989. Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
  1990. New Q&As and Q&As revised this month are marked with a bar in the side margin.
  1991. SetPreserveGlyph and font glyph preservation
  1992. Written:    7/22/91
  1993. Last reviewed:    8/1/92
  1994. TrueType’s SetPreserveGlyph call with preserveGlyph set to “true” works as you’d expect for Times and Helvetica, but it has no effect on New York, Geneva, Monaco, or Chicago. Why does SetPreserveGlyph work this way?
  1995. ___
  1996. Glyph preservation is a function of the font. It turns out that Times and Helvetica have glyphs that extend above the ascent line, thereby enabling SetPreserveGlyph to have an effect on a particular glyph. New York, Geneva, Monaco, and Chicago’s characters all fit between the ascent and descent lines, and so do not need to be compressed to fit if preserveGlyph is true. A font must have glyphs extending above or below the ascent or descent lines for SetPreserveGlyph to have an effect.
  1997. RealFont and TrueType
  1998. Written:    9/4/91
  1999. Last reviewed:    8/1/92
  2000. What is the story with RealFont and TrueType? I am finding that, of the standard System 7 fonts, only Symbol and Courier get a TRUE for 7 point.
  2001. ___
  2002. You are absolutely correct with your observation of RealFont for size 7 and certain TrueType fonts. The explanation is hidden in “The TrueType Font Format Specification” (APDA M0825LL/A), page 227:
  2003. The “head” FontHeader table contains a field “lowestRecPPEM,” which indicates the “lowest recommended pixel number per Em,” or, in other words, the “smallest readable size in pixels.” As it turns out, the Font Manager in its wisdom uses this information for the value it returns from RealFont. Note that for higher resolution devices, a point size of 7 does *not* correspond to 7 pixels; but as the unit “point” is 1/72 inch, and the screen resolution is (approximately) 72 dpi, the result corresponds to reality in this case.
  2004. The value for lowestRecPPEM can be arbitrarily set by the Font designer. We all know that small point sizes on low-resolution devices never look “great,” and even less so for outline fonts. Courier and Symbol have lowestRecPPEM = 6, while the other outline fonts in the System have lowestRecPPEM = 9. This doesn’t really mean that Courier and Symbol in size 7 (TrueType) look better than Times or Helvetica under the same conditions. It means the font designer had higher standards (or was in a different mood) when he choose lowestRecPPEM = 9.
  2005. Where to find OutlineAccessLib
  2006. Written:    12/9/91
  2007. Last reviewed:    8/1/92
  2008. Is the OutlineAccessLib library, which will provide standardized access routines to TrueType font outline bezier data, available yet? I have been unable to find this in the last few Developer CDs or the MPW 3.2 C release CD.
  2009. ___
  2010. The OutlineAccessLib is now available (although somewhat disguised and hidden) on the Developer CD Vol. X (and later); it is included in the code accompanying the article “Curves ahead” in issue #8 of develop.
  2011. SetOutlinePreferred affects only calling application
  2012. Written:    3/9/92
  2013. Last reviewed:    8/1/92
  2014. Is the property that is managed by SetOutlinePreferred and GetOutlinePreferred kept on an application-by-application basis? In other words, will calling SetOutlinePreferred affect only my application? As the current value of outlinePreferred is saved in a PICT, will playing a PICT affect the playing application’s current outlinePreferred setting? I assume that outlinePreferred is not an attribute of a GrafPort; is this true?
  2015. ___
  2016. The outlinePreferred setting is stored as a low-memory global value for your application. It is saved and restored during context switches, so it only effects your application and no one else’s.
  2017. DrawPicture should not alter the state of the global for you. While DrawPicture internally may set or reset this value, it’s supposed to put it back the way it found it when it is done. So, playing a PICT will not affect the current application’s outline settings.
  2018. And no, OutlinePreferred is not part of a grafport (as mentioned above.)
  2019. QuickDraw doesn’t draw ASCII 32 ($20) character
  2020. Written:    3/18/92
  2021. Last reviewed:    8/1/92
  2022. My TrueType font has all 256 characters defined with a unique glyph. I have been unable to draw the $20 (space) character. DrawChar, DrawText, DrawString and DrawJust all ignore this character in the font and draw a blank character. How can I draw it?
  2023. ___
  2024. Unfortunately, the problem with the space character not being drawn is hard-coded into the text-drawing routine in the core of QuickDraw. ASCII 32 is always “optimized away,” regardless of the font being used, regardless of the particular circumstances. The only workaround is to put the corresponding character elsewhere in the ASCII character encoding (or, if this is not possible, to use an additional font).
  2025. You are lucky that TrueType fonts always render the ASCII code 13 (carriage return) if it has a glyph in the font; for bitmap fonts, if the character drawing happens with scaling, or with foreground/background colors different from black/white, even the CHR(13) drawing has been optimized away.
  2026. How to Construct Word-Break Tables
  2027. Text        M.TE.WordBreakTables
  2028. Revised by:        March 1988
  2029. Written by:    Mark Davis    November 1987
  2030. This technical note describes how to construct auxiliary break tables for use with the FindWord routine in the Script Manager.
  2031. Constructing break tables
  2032. The FindWord algorithm finds word boundaries by determining where words should not be broken. For example, “re-do” is one word: it should not be broken at the hyphen. In other words, a sequence of the form: (letter, hyphen, letter) should not be broken between the first and second or second and third character. This is called a continuation sequence. The algorithm used by the FindWord routine allows for continuation sequences of lengths one, two and three. Examples of a sequence of length two include (letter, letter), or (number, number). For a length of one, there is only one sequence, consisting of the characters of type nonBreaking: these characters are never separated from preceding or following characters.
  2033. For most scripts, this information about continuation sequences is packed into a table for use by the FindWord algorithm. (For complex scripts like Japanese, a different algorithm is used for portions of the script.) The default break tables for a given script can be overridden by a user-specified breakTable parameter, but should only be used for known scripts. That is, before overriding the breakTable parameter, the programmer should first check the script of the current font.
  2034. A break table consists of two sections, a 256 byte character type table followed by a character triple table.
  2035. The character type table is indexed by the character’s ASCII code and contains one type value for each character. The character types in the table are limited to values between 1 and 31. There are two distinguishing values: the type nonBreaking (= 1) indicates that the character is non-breaking; it always continues a word. The type wild (=0) indicates that the character may or may not break, depending on information in the character triple table, as described below.  Otherwise, the choice of numbers to represent character types is completely arbitrary.
  2036. For example, the following in MPW Assembler defines character types for use in a word-selection break table, then sets up a character type table using an assembly macro (setByte) to store character type values in an array.  (Note that the character types could  have been defined with equate definitions (EQU), rather than using the record structure.)   Writing the setByte macro is left as an exercise to the reader. Note that the break value is the default. This value is not distinguished, but should have no continuation sequences.
  2037. ;============================================================
  2038. charWordRec        record        0
  2039. wild            ds.b        1    ; constant! not in char table.
  2040. nonbreak        ds.b        1    ; constant! non-breaking space.
  2041. letter            ds.b        1    ; letters.
  2042. number            ds.b        1    ; digits.
  2043. break            ds.b        1    ; always breaks.
  2044. midLetter        ds.b        1    ; a'a.
  2045. midLetNum        ds.b        1    ; a'a 1'1.
  2046. preNum            ds.b        1    ; $, etc.
  2047. postNum        ds.b        1    ; %, etc.
  2048. midNum            ds.b        1    ; 1,1.
  2049. preMidNum        ds.b        1    ; .1234.
  2050. blank            ds.b        1    ; spaces and tabs.
  2051. cr            ds.b        1    ; add carriage return
  2052.             endr
  2053. ;============================================================
  2054.     with        charWordRec
  2055. wordTable
  2056.     dcb.b        256,break
  2057.     setByte    wordTable,nonBreak,$ca
  2058.     setByte    wordTable,letter,('A','Z'),('a','z')('Ä','ü')
  2059.     setByte    wordTable,letter,'Æ','Ø','æ','ø',('À','œ'),'ÿ'
  2060.     setByte    wordTable,midLetter,'-'
  2061.     setByte    wordTable,midLetNum,$27,'’'
  2062.     setByte    wordTable,number,('0','9')
  2063.     setByte    wordTable,preNum,'$','¢','£','¥'
  2064.     setByte    wordTable,postNum,'%'
  2065.     setByte    wordTable,midNum,','
  2066.     setByte    wordTable,preMidNum,'.'
  2067.     setByte    wordTable,blank,$00,' ',$09
  2068.     setByte    wordTable,cr,$0d
  2069.     endWith
  2070. ;============================================================
  2071. The character triple table is a coded representation of a list of continuation sequences. It consists of a list of packed one word triples, preceded by a length word. This length word contains the number of triples minus one. Each triple contains three character types, either as derived from the charType table or the special type wild (= zero). The three types in a triple are packed into fields five bits apiece, with the most significant bit in the word cleared.  The first type in the triple is the leftmost. 
  2072. A continuation sequence of length three (xyz) is represented by entering three triples into the triple list: xyz, *xy, and yz* (where ‘*’ stands for the type wild, which is always zero). 
  2073. A continuation sequence of length two (xy) is represented by entering two triples into this list: *xy, and xy*. A continuation sequence of length one has no entry in the triple list: the character type is simply nonBreaking.
  2074. Note that the type wild cannot appear as the middle element of a triple. The words in the triple table must be sorted in ascending numerical order for future compatibility.
  2075. The following is an example of how a character triple table could be coded. The defSeq macro takes a continuation sequence as a parameter, and enters a set of triples into an internal array. The dumpSeq macro sorts the triples, and stores them in the proper order with dc.w commands.  Once again, writing the macros defSeq and dumpSeq is left as an exercise for the reader.
  2076. ;============================================================
  2077.     with        charWordRec
  2078.     defSeq        letter,letter
  2079.     defSeq        letter,preMidNum,letter
  2080.     defSeq        letter,midLetter,letter
  2081.     defSeq        letter,midLetNum,letter
  2082.         
  2083.     defSeq        number,number
  2084.     defSeq        number,letter
  2085.     defSeq        number,midNum,number
  2086.     defSeq        number,midLetNum,number
  2087.     defSeq        number,preMidNum,number
  2088.     defSeq        number,postNum
  2089.     defSeq        preNum,number
  2090.     defSeq        preMidNum,number
  2091.     defSeq        blank,blank
  2092.     defSeq        blank,cr
  2093.     endWith
  2094. ;============================================================
  2095.     dc.w    ((wordEnd-wordBegin)/2)-1    ; length word.
  2096. wordBegin
  2097.     dumpSeq
  2098. wordEnd
  2099. ;============================================================
  2100. A series of blanks should generally select as a single word. Make certain, however, that a carriage return does not continue a word to the right (note how it has a separate character type from blank for this reason), otherwise word selection and wrapping do not work properly across paragraphs.
  2101. Extensions
  2102. The values 16-31 in the character type table entry for null ($00) (the first byte in the character type table) are reserved by Apple for future expansion. The use of one of these values indicates the presence of a supplementary table after the triple table.
  2103. Further Reference:
  2104. •    The Script Manager 
  2105. Ï◊#ˇ ˇˇˇˇ#◊†Ç 
  2106. /ZÅ#
  2107.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  2108. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  2109. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  2110. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  2111. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  2112.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  2113. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  2114. IR.°dONLNdz<ç(ßZThe Appearance of Text
  2115. °dONLNdå<õZ*Text°dONLNdåÜõ˛(∑§M.TE.Appearance
  2116. °dONLNd-ß<≥t(œZ Revised by:°dONLNd:ß≈≥˛(œ„
  2117. March 1988°dONLNdE≥<øq(€Z Written by:°dONLNdQ≥Ñø–)HGinger Jernigan°dONLNda≥±ø˛(€œ
  2118. November 1986°dONLNdoÀ<◊Ä(ÛZThis technical °dONLNd~ÀÄ◊˛)DKnote describes why text doesn’t always look the way you expect depending on°dONLNd ◊<„æ(ˇZthe environment you are in. X°dONLNdʸ<¿*%There are a number of °dONLNd¸¸¿˛)Ñ=Macintosh text editing applications where layout is critical.°dONLNd;<–(0ZUnfortunately, text on a newer °dONLNdZ–˛)î;machine sometimes prints differently than text on a 64K ROM°dONLNdñ< í(<ZDMacintosh. Let’s examine some differences you should expect and why.°dONLNd€,<8É*BThe differences we will consider here are only differences in the °dONLNd,É8˛(T°layout of text lines (line°dONLNd88<DG(`Z;layout), not differences in the appearance of fonts or the °dONLNds8GD˛(`e'differences between different printers.°dONLNdõD<P˙(lZ*Differences in line layout may affect the °dONLNd≈D˙P˛)æ5position of line, paragraph and page breaks. The four°dONLNd˚P<\r(xZEvariables that can affect line layout are fonts, the printer driver, °dONLNd@Pr\˛(xêthe font manager mode, and°dONLNd[\<h_(ÑZROMs.
  2119. °dONLNdaÄ<è`*'Fonts
  2120. °dONLNdgõ<ßà*Every font on a °dONLNdwõà߲)LIMacintosh contains its own table of widths which tells QuickDraw how wide°dONLNd¡ß<≥ë(œZcharacters are on °dONLNd”ßë≥˛)UJthe screen. For every style point size there is a separate table which may°dONLNd≥<øÑ(€Zcontain widths °dONLNd-≥Ñø˛)HOthat vary from face to face and from point size to point size. Character widths°dONLNd}ø<À(ÁZ0can vary between point sizes of characters even °dONLNd≠øÀ˛)‚.in the same face. In other words, fonts on the°dONLNd‹À<◊(ÛZ-screen are not necessarily linearly scalable.°dONLNd
  2121. „<Ô÷*XNon-linearity is not normally a problem since most fonts are designed to be as close to °dONLNdb„÷Ô˛( Ù    linear as°dONLNdlÔ<˚ã(ZHpossible. A font face in 6 point has very nearly the same scaled widths °dONLNd¥Ôã˚˛(©of the same font face in°dONLNdÕ˚<&(#Z024 point (plus or minus round-off or truncation °dONLNd˝˚&˛)Í*differences). QuickDraw, however, requires°dONLNd(<r(/ZEonly one face of any particular font to be in the System file to use °dONLNdmr˛(/êit in any point size. If only a°dONLNdç<í(;ZG10 point face actually exists, QuickDraw may scale that face to 9, 18, °dONLNd‘í˛(;∞24 (or whatever point°dONLNdÍ<+:(GZ8size) by performing a linear scale of the 10 point face.°dONLNd$7<CT*This °dONLNd)7TC˛)Tcan cause problems. Suppose a document is created on one Macintosh containing a font°dONLNd~C<OÇ(kZIthat only exists in that System file in one point size, say 9 point. The °dONLNd«CÇO˛(k†document is then taken to°dONLNd·O<[©(wZHanother Macintosh with a System file containing that same font but only °dONLNd)O©[˛(w«in 24 point. The°dONLNd:[<gu(ÉZBdocument may, in fact, appear differently on the two screens, and °dONLNd|[ug˛(Éìwhen it is printed, will have°dONLNdög<s°(èZline breaks (and thus °dONLNd∞g°s˛)eGparagraph and page breaks) occurring in different places simply because°dONLNd¯s<”(õZYof the differences in character widths that exist between the 9 point and 24 point faces. ◊X◊
  2122. *QThe Appearance of Text(Ï1) of 3ˇ°¿Ù%%DSIDICT:_cv
  2123. currentdict /bu known {bu}if
  2124. userdict /_cv known not{userdict /_cv 30 dict put}if
  2125. _cv begin
  2126. /bdf{bind def}bind def
  2127. currentscreen/cs exch def/ca exch def/cf exch def
  2128. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  2129. /ss{//cf //ca //cs setscreen}bdf
  2130. /stg{ss setgray}bdf
  2131. /strgb{ss setrgbcolor}bdf
  2132. /stcmyk{ss cvcmyk}bdf
  2133. /min1{dup 0 eq{pop 1}if}bdf
  2134. end
  2135. currentdict /bn known {bn}if
  2136. †ø◊#ˇ ˇˇˇˇ#◊ 
  2137. IR,Times
  2138. .+6-Macintosh Technical Notes /4/˘
  2139. °dONLNd)8ò*'The Printer Driver
  2140. °dONLNdDP*/Even when the printer you are using has a much °dONLNdBDP⁄)*higher resolution than what the screen can°dONLNdmP\¬(x6\show, printer drivers perform line layout to match the screen layout as closely as possible.°dONLNd htØ*TThe line layout performed by printer drivers is limited to single lines of text and °dONLNdhØt⁄(êÕdoes not°dONLNd'tÄ(ú63change line break positions within multiple lines. °dONLNdZtÄ⁄)Í-The driver supplies metric information to the°dONLNdàÄåæ(®6$application about the page size and °dONLNd¨Äæå⁄)¶=printable area to allow the application to determine the best°dONLNdÍåòø(¥6#place to make line and page breaks.°dONLNd§∞¸*,Printer driver line layout does affect word °dONLNd:§¸∞⁄)‰(spacing, character spacing and even word°dONLNdc∞º(ÿ67positioning within a line. This may affect the overall °dONLNdö∞º⁄)˘*appearance of text, particularly when font°dONLNd≈º»∑(‰6"substitutions are made or various °dONLNdÁº∑»⁄)ü=forms of page or text scaling are involved. But print drivers°dONLNd%»‘˙(6+NEVER change line, paragraph or page break °dONLNdP»˙‘⁄)‚-positions from what the application or screen°dONLNd~‘‡Ç(¸6specified. This means °dONLNdî‘LJ⁄)jGthat where line breaks appear on the screen, they will always appear in°dONLNd‹‡Ïr(6Kthe same place on the printer regardless of how the line layout may affect °dONLNd'‡rÏ⁄(êthe appearance within°dONLNd=ϯ>(6    the line.
  2141. °dONLNdG÷*'Operating System and ROMs
  2142. °dONLNda+7*4In this context, operating system refers to the ROM °dONLNdï+7⁄(S=$trap routines which handle fonts and°dONLNd∫7CΔ(_6!QuickDraw. Changes have occurred °dONLNd€7ΔC⁄)Æ7between the ROMs in the handling of fonts. Fonts in the°dONLNdCOI(k6964K ROMs contain width tables (as described above) which °dONLNdLCIO⁄(kgare limited to integer values.°dONLNdkO[1(w66Several new tables, however, have been added to fonts °dONLNd°O1[⁄(wOfor the newer ROMs. The newer°dONLNdø[gÇ(É6MROMs add an optional global width table containing fractional or fixed point °dONLNd [Çg⁄(Ɇdecimal values. In°dONLNdgsv(è6Maddition, there is another optional table containing fractional values which °dONLNdlgvs⁄(èîcan be scaled for the°dONLNdÇsπ(õ6$entire range of point sizes for any °dONLNd¶sπ⁄)°<one face. There is also an optional table which provides for°dONLNd„ã«(ß6&the addition (or removal) of width to °dONLNd    «ã⁄)Ø9a font when its style is changed to another value such as°dONLNdCãó°(≥6bold, outline or condensed. °dONLNd_ã°ó⁄)â=It is also possible, under the 128K ROMs, to add fonts to the°dONLNdùó£á(ø6Msystem with inherent style properties containing their own width tables that °dONLNdÍóá£⁄(ø•produce different°dONLNd¸£ØÂ(À6+character widths from derived style widths.°dONLNd(ª«g*One or all of the °dONLNd:ªg«⁄)OKabove tables may or may not be invoked depending on, first, their presence,°dONLNdÜ«”Ç(Ô6and second, the mode °dONLNdõ«Ç”⁄)jBof the operating system. The Font Manager in the newer ROMs allows°dONLNdfi”flk(˚6the application to °dONLNdÒ”kfl⁄)SNarbitrarily operate in either the fractional mode or integer mode (determined,°dONLNd    @‡φ(6in most cases, by the setting °dONLNd    ^‡†ÏÆ)àof ,
  2143. Courier°dONLNd    aflÆÎ˚) FractEnable°dONLNd    l‡˚Ï⁄)M0) as it chooses, with the default being integer.°dONLNd    ùϯ¿(6\There is one case where fractional widths will be used if they exist even though fractional °dONLNd    ˘Ï¿¯⁄(fimode°dONLNd    ˛˘s(!6is disabled. When °dONLNd
  2144. ¯sŒ)[
  2145. FScaleDisable°dONLNd
  2146. ˘Œ^)[ is used fractional widths are °dONLNd
  2147. <˘^⁄)êalways used if they exist°dONLNd
  2148. Vò(.6regardless of the setting of °dONLNd
  2149. sòÂ)Ä FractEnable°dONLNd
  2150. ~ÂÈ)M.°dONLNd
  2151. Ä*Δ(F6%Differences in line layout (and thus °dONLNd
  2152. •Δ*⁄)Æ6line breaks) may be affected by any combination of the°dONLNd
  2153. ‹*6ˆ(R60presence or absence of the optional tables, and °dONLNd *ˆ6⁄)fi1the operating mode, either fractional or integer,°dONLNd >6B¢(^6Oof the application. Any of the combinations can produce different results from °dONLNd ç6¢B⁄(^¿ the original°dONLNd öBN§(j6ROMs (and from each other).°dONLNd ∂ZfÃ*TThe integer mode on the newer ROMs is very similar to, but not exactly the same as, °dONLNd
  2154. ZÃf⁄(ÇÍthe°dONLNd frv(é6Horiginal 64K ROMs. When fonts with the optional tables present are used °dONLNd Vfvr⁄(éîon Macintoshes with°dONLNd jr~y(ö6H64K ROMs, they continue to work in the old way with the integer widths. °dONLNd ≤ry~⁄(öóHowever, on newer°dONLNd ƒ~äÃ(¶6[ROMs, even in the integer mode, there may be variations in line width from what is seen on °dONLNd
  2155. ~Ãä⁄(¶Íthe°dONLNd
  2156. #äñ(≤6:old ROMs. In the plain text style there is very little if °dONLNd
  2157. ]äñ⁄)˚*any difference (except if the global width ◊4◊˘
  2158. (Ï62) of 3(ÏôThe Appearance of Textˇ^◊#ˇ ˇˇˇˇ#◊ 
  2159. IR,Times
  2160. .+Z-Developer Support Center(-Ï
  2161. March 1988 /X/
  2162. °dONLNd<)á(EZHtable is present), but as various type styles are selected, line widths °dONLNdHá)˛(E•may vary more between°dONLNd^)<5_(QZROMs.°dONLNddA<Må*Variations in the °dONLNdvAåM˛)PNabove options, by far, account for the greatest variation in the appearance of°dONLNd≈M<Y4(uZ1lines when a document is transported between one °dONLNdˆM4Y˛)¯&Macintosh and another. Line breaks may°dONLNdY<e‰(ÅZchange position when documents °dONLNd<Y‰e˛)®4created on one system (say a Macintosh) are moved to°dONLNdqe<q(çZ(another system (like a Macintosh Plus). °dONLNdôeq˛)ƒ0Variations are more pronounced as the number and°dONLNd q<}B(ôZ8sizes of various type styles increase within a document.°dONLNdâ<ïI*In °dONLNdâIï˛)
  2163. [all cases, however, a printer driver will produce exactly the same line breaks as appear on°dONLNdbï<°(ΩZ-the screen with any given system combination.°dONLNdê≈<—¶*0Further Reference: X°dONLNd£“NfiR+
  2164. •°dONLNd•“`fi«)The Printing Manager°dONLNd∫fiNÍR(l•°dONLNdºfi`Í∑)The Font Manager°dONLNdÕÍNˆR(l•°dONLNdœÍ`ˆ…)M.IM.LaserWriterOpt ◊X◊
  2165. (ÏZThe Appearance of Text(Ï3) of 3ˇ‚◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  2166. /ZÅ#
  2167.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  2168. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  2169. .^ tK^ tK+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  2170. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  2171. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  2172.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  2173. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  2174. IR.°dONLNd{<éû(®Z'Script Manager 2.0 Date & Time Problems
  2175. °dONLNd(ç<úZ*Text°dONLNd.çkú˛(∏âM.TE.ScriptDateTime
  2176. °dONLNdB®<¥q(–Z Written by:°dONLNdN®Ñ¥¡)H John Harvey°dONLNdZ®∏¥˛(–÷
  2177. February 1990°dONLNdh¿<ÃT(ËZThis °dONLNdm¿TÃ˛)VTechnical Note describes known bugs and features in and solutions to the date and time°dONLNdƒÃ<ÿ(ÙZ*routines introduced in Script Manager 2.0. X°dONLNdÔÒ<˝(*%/From the beginning, the Macintosh’s ability to °dONLNdÒ(˝˛)Ï*handle dates was limited to a rather small°dONLNdI˝<    ı(%Z%range—slightly more than a century.  °dONLNdn˝ı    ˛)π3Enhancements to the Script Manager, introduced with°dONLNd¢    <ê(1ZSystem Software °dONLNd≤    ê˛)TK6.0, extended this range to ±35,000 years.  Unfortunately, there is a minor°dONLNd˛<!ß(=ZQbug in one of the crucial calls and a “feature” that looks like a bug in another.
  2178. °dONLNdP9<H,*' You Said It Would Be A Long Time,
  2179. Courier
  2180. °dONLNdqT<`û*_LongSecs2Date°dONLNdUûa%)b , the routine that translates a °dONLNdüT%`y)á LongDateTime°dONLNd´Uyaê)T to a °dONLNd±Tê`›) LongDateRec°dONLNdºU›a˛)M, has a°dONLNdƒa<mQ(âZbug °dONLNd»aQm˛)[caused by using a variable that has not been properly initialized.  This bug rears its ugly°dONLNd$m<y(ïZ,head when negative values are passed to the °dONLNdPmy˛)“2routine.  System Software 6.0.4 and later fix this°dONLNdÉy<Ö<(°Z8bug, and there is a simple solution for earlier systems.°dONLNdºí<ûI*8If using System Software 6.0.3 and earlier, if you call °dONLNdÙëIù´(∫g_LongSecs2Date°dONLNdí´û…)b once °dONLNdí…û˛)
  2181. before you°dONLNdü<´s(«Z really want °dONLNdüs´z)7=to use it, the variable is cleared.  After the initial call, °dONLNd\ûz™‹(«ò_LongSecs2Date°dONLNdjü‹´˛)b works°dONLNdq´<∑i(”Z
  2182. correctly.°dONLNd|√<œz* For example:°dONLNdâ€<ÁÉ*
  2183. MPW Pascal
  2184.     °dONLNdîÛ<˛™*PROCEDURE DoDateStuff;°dONLNd´˝<K*
  2185. VAR°dONLNdØ<™*
  2186.   lsecs: LongDateTime;°dONLNdΔ<•*
  2187.   ldr:   LongDateRec;°dONLNd‹<&U*
  2188. BEGIN°dONLNd‚%<0•*
  2189.   InitDateCache(dcr);°dONLNd¯/<:}*
  2190.  
  2191.   lsecs := 0;°dONLNd9<D√*
  2192.   LongSecs2Date(lsecs,ldr);°dONLNd"C<N*
  2193. +  {now you can call LongSecs2Date for real}°dONLNdNW<bP*END;
  2194. °dONLNdSm<yh*MPW C
  2195.     °dONLNdYÖ<êñ*void DoDateStuff()°dONLNdlè<öA*
  2196. {°dONLNdnô<§•*
  2197.   LongDateTime lsecs;°dONLNdÑ£<Æõ*
  2198.   LongDateRec  ldr; ◊X◊
  2199. *"'Script Manager 2.0 Date & Time Problems(Ï1) of 2ˇ°¿Ù%%DSIDICT:_cv
  2200. currentdict /bu known {bu}if
  2201. userdict /_cv known not{userdict /_cv 30 dict put}if
  2202. _cv begin
  2203. /bdf{bind def}bind def
  2204. currentscreen/cs exch def/ca exch def/cf exch def
  2205. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  2206. /ss{//cf //ca //cs setscreen}bdf
  2207. /stg{ss setgray}bdf
  2208. /strgb{ss setrgbcolor}bdf
  2209. /stcmyk{ss cvcmyk}bdf
  2210. /min1{dup 0 eq{pop 1}if}bdf
  2211. end
  2212. currentdict /bn known {bn}if
  2213. †ø Ê◊#ˇ ˇˇˇˇ#◊ 
  2214. IR,Times
  2215. .+6-Macintosh Technical Notes /4/˘,
  2216. Courier
  2217.     °dONLNd1<ï*+/* work around the bug */°dONLNd;FT*
  2218.   lsecs = 0;°dONLNd'EP©*
  2219.   LongSecs2Date(&lsecs,&ldr);°dONLNdEOZ—*
  2220. %/* now call LongSecs2Date for real */°dONLNdkYd*
  2221. }
  2222. °dONLNdm{äõ*&Any String To Date
  2223. °dONLNdÄó£Q* The routine °dONLNdåñQ¢•)9 _String2Date°dONLNdò󕣿)T was °dONLNdùóæ£⁄)=originally designed to be as forgiving as possible.  It is so°dONLNd€£Øñ(À6Tforgiving that it accepts any non-alphabetic character as a separator and accepts a °dONLNd/£ñØ⁄(À¥
  2224. single number°dONLNd=∞ºÊ(ÿ6,as a valid date.  For instance, if you pass °dONLNdiØÊª:)Œ _String2Date°dONLNdu∞:º¶)T a string like “<20” it °dONLNdç∞¶º⁄)l
  2225. generously°dONLNdòº»(‰65assumes that the less than sign (<) is intended as a °dONLNdÕº»⁄)+divider and that “20” must be intended as a°dONLNd˘…’U(Ò6Gday, since there are only 12 months in a year.  It returns a result of °dONLNd@»U‘x(ÒsnoErr°dONLNdE…x’⁄)# and a date which is°dONLNdZ’·(˝69the twentieth of the current month in the current year.  °dONLNdì’·⁄(˝7%The string “<3*3” produces March 3 of°dONLNdπ·Ìå(    6Rthe current year, while “4>1” politely gives the date April 1 of the current year.°dONLNd ˘w*OThis forgiveness really is not a bug, but a feature.  Unfortunately it isn’t a °dONLNd[˘w⁄(!ïfeature that has been°dONLNdqÖ(-6Lgreatly appreciated in the developer community.  For that reason, the rules °dONLNdΩÖ⁄(-£for date and time°dONLNdœB(96    dividers °dONLNdÿB⁄)*Tare tighter in System 7.0.  Current thinking is that all list separators now used in°dONLNd-)B(F6'itl0'°dONLNd3B*j)*= resources will be allowed with a few common date separators °dONLNdpj*⁄(Fàused in the U.S. (e.g.,°dONLNdà*6%(R6;colon (:) and hyphen (-)).  For now, it is important to be °dONLNd√*%6⁄(RC'aware of, shall we say, the flexibility°dONLNdÎ7C%(_6of °dONLNdÓ6%By)
  2226. _String2Date°dONLNd˙7yCs)T9 and avoid thinking of it as an intelligent date parser. °dONLNd37sC⁄)˙ If you want to parse°dONLNdIDPã(l6something, you can use °dONLNd`CãOÊ)s
  2227. _IntlTokenize°dONLNdmDÊPÍ)[.°dONLNdotÄÇ(ú6Further Reference: ü4ü˘°dONLNdÇÅ*ç.+
  2228. •°dONLNdÑÅ<çç)Inside Macintosh°dONLNdîÅçç()Q, Volume V, The Script Manager°dONLNd≥ç*ô.(µH•°dONLNdµç<ô¨)The Script Manager 2.0°dONLNdÀç¨ô)p, Interim Chapter (DTS) ◊4◊˘
  2229. (Ï62) of 2(ÏJ'Script Manager 2.0 Date & Time Problemsˇ @◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  2230. /ZÅ#
  2231.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  2232. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  2233. .eRSeRS+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  2234. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  2235. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  2236.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  2237. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  2238. IR.°dONLNd{<é§(®Z)Drawing Characters into a Narrow GrafPort
  2239. °dONLNd*ç<úZ*Text°dONLNd0ç`ú˛(∏~M.TE.TextInNarrowGP
  2240. °dONLNdD®<¥t(–Z Revised by:°dONLNdQ®≈¥˛(–„
  2241. March 1988°dONLNd\¥<¿q(‹Z Written by:°dONLNdh¥Ñ¿–)HGinger Jernigan°dONLNdx¥æ¿˛(‹‹ January 1986 ÎXΰdONLNdÖ⁄<Ê’(ZWhen you draw a character into °dONLNd§⁄’Êfi)ôa ,
  2242. Courier°dONLNd¶ŸfiÂ)    GrafPort°dONLNdÆ⁄Ê˛)80, your program will die with an address error if°dONLNdflÁ<Ûç(Zthe width of the °dONLNdÊçÚ≈)QGrafPort°dONLNd¯Á≈Û˚)8  is smaller °dONLNdÁ˚Û˛)64than the width of the character. If you check before°dONLNd9Ù<›(Z$drawing the character to see if the °dONLNd]Û›ˇ)°GrafPort°dONLNdeÙ˛)8/ is wide enough, you can avoid this unfortunate°dONLNdï< c((Ztragedy.°dONLNdû0<<¶*0Further Reference: [X[°dONLNd±=NIR+
  2243. •°dONLNd≥=`Iñ)    QuickDraw ◊X◊
  2244. (ÏZ)Drawing Characters into a Narrow GrafPort(Ï1) of 1ˇ°¿Ù%%DSIDICT:_cv
  2245. currentdict /bu known {bu}if
  2246. userdict /_cv known not{userdict /_cv 30 dict put}if
  2247. _cv begin
  2248. /bdf{bind def}bind def
  2249. currentscreen/cs exch def/ca exch def/cf exch def
  2250. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  2251. /ss{//cf //ca //cs setscreen}bdf
  2252. /stg{ss setgray}bdf
  2253. /strgb{ss setrgbcolor}bdf
  2254. /stcmyk{ss cvcmyk}bdf
  2255. /min1{dup 0 eq{pop 1}if}bdf
  2256. end
  2257. currentdict /bn known {bn}if
  2258. †øX◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  2259. /ZÅ#
  2260.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  2261. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  2262. .eRSeRS+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  2263. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  2264. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  2265.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  2266. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  2267. IR.°dONLNd{<éø(®Z
  2268. Fond of FONDs
  2269. °dONLNdç<úZ*Text°dONLNdç£ú˛(∏¡
  2270. M.TE.FONDs
  2271. °dONLNd®<¥q(–Z Written by:°dONLNd+®Ñ¥Ÿ)H     Joseph Maurer°dONLNd>®À¥˛(–È     May 1992°dONLNdH¿<ÃΩ(ËZThis Technical Note takes °dONLNdb¿ΩÃF)Åthe place of Tech Note #26°dONLNd|¿FÃK)â,°dONLNd}¿KÃ˛)$ “Character vs. String Operations in°dONLNd¢Ã<ÿ|(ÙZ QuickDraw” °dONLNd≠Ã|ÿ˛)@Iby Bryan Stearns (March 1988), which pointed out the possible differences°dONLNd˜ÿ<‰¶(ZMbetween the results of a StringWidth call and successive calls to CharWidth. °dONLNdDÿ¶‰˛(ƒThis Note updates°dONLNdV‰<#( Z-and brings into a broader context the issues °dONLNdɉ#˛)Á+related to text measuring. It also provides°dONLNdØ<¸Ê(ZSadditional documentation on font family resources ('FOND's), and addresses various °dONLNdʸ˛(other°dONLNd¸<B($Z7frequently asked questions related to the Font Manager. 3X3
  2272. °dONLNdA-<<è*4 Introduction
  2273. °dONLNdNH<T~*CEvery Macintosh developer needs to draw text in a GrafPort, and to °dONLNdëH~T˛(púspecify typeface, size, and°dONLNd≠T<`∫(|Zstyle. In most cases, there °dONLNd…T∫`˙)~Aare no problems, and application developers don’t need to have in°dONLNd
  2274. T˙`˛(|-°dONLNd `<l(àZ&depth knowledge of the Font Manager’s °dONLNd1`l˛)Ã0inner workings and the data structures involved.°dONLNdbl<xÃ(îZTSometimes, however, the results on the screen or on printed output may be different °dONLNd∂lÃx˛(îÍ    from what°dONLNd¿x<Ñ(†Z,you expected. Then, usually, DTS comes into °dONLNdÏxÑ˛)‹.play to figure out what the problem is and how°dONLNdÑ<êx(¨ZDto fix it. This Note is based on sharp developer questions from the °dONLNd_Ñxê˛(¨ñlast year or so, which point°dONLNd|ê<ú˘(∏Z'mainly at shortcomings of the existing °dONLNd£ê˘ú˛)Ω6Font Manager architecture, inconsistencies in its data°dONLNd⁄ú<®(ƒZ.structures, and missing details in the documen°dONLNd    ú®4)⁄tation.°dONLNd¥<¿\(‹ZWe’ll °dONLNd¥\¿˛) Qstart with a historical overview, which discusses the introduction of font family°dONLNdi¿<Ñ(ËZHdescription resources ('FOND's) back in 1986, explains the consequences °dONLNd±¿‘Ã˙(ËÚof non°dONLNd∑¿˙Ã˛)&-°dONLNd∏Ã<ÿ˝(ÙZaproportionally scaling fonts, and covers  non-registration and volatility of font family numbers.°dONLNd‰<ã*EWe will then deal with the Font/DA Mover and the built-in “Mover” of °dONLNd_‰ã˛( ©the Finder in System 7.°dONLNdw<¸Ÿ(ZQWe discuss a number of not-so-well-known aspects of moving fonts in and out of a °dONLNd»Ÿ¸˛(˜suitcase°dONLNd—¸<N($Z4file, and recommend that you altogether abandon the °dONLNd¸N˛($l resource type 'FONT'. We'll also°dONLNd&<∏(0Zcomment on font names, °dONLNd=∏˛)|Aand show you how to put separate stylistic variants of a typeface°dONLNd< Ï(<Z#together into one font family. And °dONLNd¢Ï ˛)∞4we provide documentation on the ffVersion field of a°dONLNd◊ <,¡(HZQ'FOND' (accompanied by a disclaimer and another piece of irritating information).°dONLNd)8<Dô*@The main body of this Note addresses how the Font Manager works °dONLNdi8ôD˛(`∑in the FMSwapFont°dONLNd{D<P{(lZ
  2275. context, and °dONLNdàD{P˛)?Mgives information on the scaling factors in the FMOutput structure and on the°dONLNd÷P<\©(xZchanges introduced by °dONLNdÏP©\˛)mBTrueType. We again took the examples of unexpected behavior (under°dONLNd    /\<h…(ÑZRcertain circumstances) from developer questions. Thanks for helping document this!°dONLNd    Çt<Ä)*4Determining the width of text, as required for line °dONLNd    ∂t)IJ)Ì,layout, is sometimes trickier than you might°dONLNd    „Ä<ån(®Z
  2276. think. We °dONLNd    ÌÄnå˛)2Pwill document the effects of SetFractEnable in more detail and mention some more°dONLNd
  2277. >å<ò†(¥Zline layout problems. ◊X◊
  2278. *8
  2279. Fond of FONDs(Ïˇ1) of 12ˇ°¿Ù%%DSIDICT:_cv
  2280. currentdict /bu known {bu}if
  2281. userdict /_cv known not{userdict /_cv 30 dict put}if
  2282. _cv begin
  2283. /bdf{bind def}bind def
  2284. currentscreen/cs exch def/ca exch def/cf exch def
  2285. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  2286. /ss{//cf //ca //cs setscreen}bdf
  2287. /stg{ss setgray}bdf
  2288. /strgb{ss setrgbcolor}bdf
  2289. /stcmyk{ss cvcmyk}bdf
  2290. /min1{dup 0 eq{pop 1}if}bdf
  2291. end
  2292. currentdict /bn known {bn}if
  2293. †ø∫◊#ˇ ˇˇˇˇ#◊ 
  2294. IR,Times
  2295. .+6-Macintosh Technical Notes /4/˘
  2296. °dONLNd+w*Finally, this Note °dONLNdw+⁄)_Cincludes sample code that puts the OutlineMetrics call to work, and°dONLNdX+7(S60determines text bounding boxes for bitmap fonts.
  2297. °dONLNdâO^æ*'Some FOND Background
  2298. °dONLNdüjvP* Originally (°dONLNd´jPv£)8Inside Macintosh°dONLNdªj£v“)S Volume °dONLNd√j“v⁄)/5I, Chapter 7), all font-related data was contained in°dONLNd˘vÇ(û6,resources of type 'FONT'. For a font number °dONLNd%vÇ⁄)Î*within the range 0....255, and a font size°dONLNdPÇéh(™6Frestricted to less than 128, the (unnamed) 'FONT' resource with an ID:°dONLNdòö<¶”+$128*(font number) + (font size)°dONLNd∏≤æ∏(⁄6"contained the bitmap font strike, °dONLNd⁄≤∏æ⁄)†6while the 'FONT' resource with ID = 128*(font number),°dONLNdæ Ï(Ê6.corresponding to font size 0, did not contain °dONLNd?æÏ ⁄)‘1any data, but its resource name provided the font°dONLNdq ÷∑(Ú6Yfamily name. QuickDraw took care of stylistic variants like italic, bold, shadow, and so °dONLNd  ∑÷⁄(Ú’on; if a°dONLNd”÷‚(˛65user had a specifically fine-tuned font strike for a °dONLNd÷‚»)¸#stylistic variant, QuickDraw would °dONLNd+÷»‚⁄)¥not°dONLNd/‚ÓÓ(
  2299. 6.automatically substitute it when drawing text.°dONLNd^˙—*(For aesthetic reasons, bitmap fonts for °dONLNdÜ˙—÷)π5different sizes were usually designed with widths non°dONLNdª˙÷⁄("Ù-°dONLNdº
  2300. (.66proportional to the point size. For example, the text °dONLNdÚ
  2301. º)ı%“Show the difference in text widths” °dONLNdº⁄)Ødrawn°dONLNdÆ(:6Pwith Courier 9 measures 170 pixels, whereas the same text drawn with Courier 18 °dONLNdmÆ⁄(:Ãmeasures°dONLNdv*Î(F6'374 pixels, which is 10% more than you °dONLNdùÎ*⁄)”-expect. (By the way, this is bad news for the°dONLNdÀ*63(R6:ImageWriter printer driver. When “Best” mode (144 dpi) is °dONLNd*36⁄(RQ$selected and text in Courier 9 is to°dONLNd*6B(^62be printed, the printer driver uses Courier 18 to °dONLNd\6B⁄)Î,render the 9-point font size on the paper at°dONLNdâBNë(j6Ptwice the screen resolution, and obviously has big trouble compensating for the °dONLNdŸBëN⁄(jØ10% difference°dONLNdËNZ[(v6in text width.)°dONLNd¯frU*
  2302. On the other °dONLNdfUr⁄)=Phand, given that only integer character widths (in QuickDraw’s 72 dpi units) are°dONLNdVr~F(ö6
  2303. possible, °dONLNd`rF~⁄).Pproportional font scaling is compromised anyway.  Accumulated rounding errors in°dONLNd±~ä%(¶6:text measuring, particularly for scaled fonts, contribute °dONLNdÎ~%ä⁄(¶C"to the headaches of many Macintosh°dONLNdäñS(≤6Bprogrammers. The computed text widths (vital for positioning text °dONLNdPäSñ⁄(≤qprecisely and for line layout°dONLNdnñ¢[(æ6algorithms to °dONLNd|ñ[¢⁄)CKjustify text) sometimes change quite abruptly when the user removes or adds°dONLNd»¢Æk( 6certain font sizes.°dONLNd‹∫Δ]*BThe introduction of the LaserWriter, and the success of Macintosh °dONLNd∫]Δ⁄(‚{in the desktop publishing°dONLNd8Δ“Ç(Ó6Narena,  required an extension of the original Font Manager architecture. This °dONLNdÜΔÇ“⁄(Ó†extension is based°dONLNdô“fi®(˙6on the concept of “font family °dONLNd∏“®fi⁄)ê<description” resources of type 'FOND', and on a new resource°dONLNdıfiÍÿ(6)type 'NFNT' for the data of the existing °dONLNd    fiÿÍK)¿'FONT' resources (see °dONLNd    4fiKÍù)sInside Macintosh°dONLNd    DfiùÍ⁄)R  Volume IV,°dONLNd    P͈N(6 Chapter 5).°dONLNd    \t*BThe 'FOND' resource stores size-independent information about the °dONLNd    ût⁄(*ífont family, and its°dONLNd    ≥ª(66#resource ID is the font number (in °dONLNd    ÷ª⁄)£8the range 0...32767). The resource name of the 'FOND' is°dONLNd
  2304. &˜(B61the font name, and it contains a variable-length °dONLNd
  2305. @˜&p)flfont association table°dONLNd
  2306. Vp&w)y, °dONLNd
  2307. Xw&⁄)which references the°dONLNd
  2308. m&2à(N6font strikes belonging °dONLNd
  2309. Ñ&à2⁄)pDto a specific font family. These references include size, style, and°dONLNd
  2310. …2>b(Z6resource ID of °dONLNd
  2311. ÿ2b>⁄)JGthe 'NFNT' or 'FONT' resource containing the bitmap font data. TrueType°dONLNd  >Jˆ(f61fonts were retrofitted into this scheme, and are °dONLNd Q>ˆJ⁄)fi2identified as font strike resources for point size°dONLNd ÑJVm(r6Lzero.  Any reference to point size zero refers to a resource of type 'sfnt'.°dONLNd —bn7*Note:°dONLNd ◊b<n6)$3The range 0...32767 for font numbers is subdivided °dONLNd
  2312. b6n∂)˙into ranges for the various°dONLNd &n<zó(ñZscript systems (see°dONLNd 9nózÒ)[ Inside Macintosh °dONLNd KnÒz)ZVolume °dONLNd Rnz∂))VI, pages 13-8 and 14-22, and°dONLNd pz<Ü∫(¢ZM.TE.FontsAndScripts). °dONLNd áz∫Ü∂)~0This restricts the range of font numbers for the°dONLNd ∏Ü<íö(ÆZHRoman script to 0...16383, with 0, 1, and 16383 reserved for the system. ◊4◊˘
  2313. (Ï62) of 12(Ï∑
  2314. Fond of FONDsˇD◊#ˇ ˇˇˇˇ#◊ 
  2315. IR,Times
  2316. .+Z-Developer Support Center(-ÛMay 1992 /X/
  2317. °dONLNd`)†(E~ Since Apple °dONLNd †)⁄)@?originally intended fonts to be referenced by their font family°dONLNdL)`5Ò(Q~numbers, DTS attempted to °dONLNdf)Ò5Ö)ëregister those numbers (see °dONLNdÇ)Ö5⁄)îInside Macintosh°dONLNdì5`A¨(]~Volume I, page °dONLNd¢5¨A⁄)L:219 and Volume IV, page 31).  This failed—not only because°dONLNd›A`Mi(i~5the number of fonts registered grew greater than the °dONLNdAiM⁄(iánumber of font family°dONLNd(M`Yå(u~numbers °dONLNd0MåY⁄),Cavailable, but also because the Font/DA Mover (version 3.8, shipped°dONLNdtY`e-(Å~&with System 6), and the “Mover” built °dONLNdöY-e⁄)Õ into the System 7 Finder resolve°dONLNdªe`q¬(ç~Gconflicts between font IDs (which happened anyway!) by renumbering the °dONLNde¬q⁄(ç‡fonts°dONLNdq`}∏(ô~on-the-fly. There °dONLNdq∏}⁄)X7is no font ID registration any more—except for the very°dONLNdR}`âö(•~
  2318. special case °dONLNd_}öâ⁄):@of Japanese Kanji 'FOND'–'fbit' IDs, and potentially for Korean,°dONLNd†â`ï(±~$Chinese and other double-byte fonts.°dONLNdΔ°`≠+*'As early as April 1988, M.IM.FontNames °dONLNd̰+≠⁄)À!recommended the use of font names°dONLNd≠`πZ(’~2rather than font family numbers.  Since then, the °dONLNdA≠Zπ⁄)˙recommendation has been°dONLNdYπ`≈•(·~reinforced in °dONLNdgπ•≈˘)EInside Macintosh°dONLNdwπ˘≈Ç)T Volume VI, page 12-16. °dONLNdèπÇ≈⁄)âFortunately, most°dONLNd°≈`—£(Ì~
  2319. applications     °dONLNdÆ≈£—⁄)C3have been good about following this recommendation.°dONLNd‚—`›≠(˘~Unfortunately, °dONLNdÒ—≠›⁄)M5some exceptions remain, even in Apple’s own software.°dONLNd'›`ÈÈ(~QuickDraw Pictures created °dONLNdB›ÈÈ⁄)â/without 32-Bit QuickDraw refer to fonts by font°dONLNdrÈ`ı¡(~family number only!°dONLNdá<
  2320. ()Z For obvious °dONLNdì
  2321. ˛)CIreasons of upward compatibility (to maintain existing fonts, and to avoid°dONLNd›
  2322. <j(5Z>reflowing of existing documents), the introduction of 'FOND's °dONLNd
  2323. j˛(5àdid not solve all the problems.°dONLNd;<%fi(AZ$This is what this Note is all about.
  2324. °dONLNd`=<Lù*'
  2325. Moofing Fonts
  2326. °dONLNdnX<dˆ*VThe Font/DA Mover utility has evolved into version 4.1, which knows about 'sfnt's. It °dONLNdƒXˆd˛(Äis°dONLNd«d<pà(åZavailable on the °dONLNdÿdàpÀ)L Developer CD°dONLNd‰dÀpŒ)C °dONLNdÂdŒpÎ)Series°dONLNdÎdÎp∑)*  disc, path “Tools & Apps (Moof!): Misc. °dONLNdd∑p˛)ÃUtilities:”. The°dONLNd&p<|G(òZ5Finder in System 7 incorporates its own “Mover” (see °dONLNd[pG|ô(òeInside Macintosh°dONLNdkpô|Ù)R Volume VI, page °dONLNd|pÙ|˙)[9°dONLNd}p˙|˛)-°dONLNd~|<àÇ(§Z@33), which makes the Font/DA Mover redundant for System 7 users.°dONLNdøî<†z*?Given the combinatorial explosion of all imaginable situations °dONLNd˛îz†˛(ºòwith 'FOND's, 'FONT's,°dONLNd†<¨î(»ZH'NFNT's and 'sfnt's, and stylistic variations of fonts belonging to the °dONLNd]†î¨˛(»≤same family, the font°dONLNds¨<∏+(‘Z1moving job deserves respect. The following notes °dONLNd§¨+∏˛)Ô*cover some less well-known aspects of this°dONLNdœ∏<ƒi(‡Z    business.°dONLNdŸ—N›R+•°dONLNd€—[›Õ)
  2327. If an old “standalone” ,
  2328. Courier°dONLNdÚ–Õ‹˜)r'FONT'°dONLNd¯—˜›r)* (without corresponding °dONLNd–r‹ú){'FOND'°dONLNd—ú›“)*  resource) °dONLNd!—“›⁄)6is°dONLNd$›[Èä(y:moved into a suitcase file, Font/DA Mover or the System 7 °dONLNd^›äÈ⁄(®Mover creates a°dONLNdnÍ[ˆÑ(yminimal °dONLNdvÈÑıÆ))'FOND'°dONLNd|ÍÆˆ*)* resource on-the-fly. This °dONLNdóÈ*ıT)|'FOND'°dONLNdùÍTˆœ)* has no tables, and nearly °dONLNd∏Íœˆ⁄){all°dONLNdºˆ[i(yits °dONLNd¿ˆi⁄)Kfields are zeroed. The System 7 Finder also converts the resource type from°dONLNd     [Ö(+y'FONT'°dONLNd    Öî)* to °dONLNd    îæ)'NFNT'°dONLNd    æΔ)*7;  unfortunately, the Font/DA Mover keeps the resource °dONLNd    SΔ⁄(+‰type°dONLNd    X[Ö(8y'FONT'°dONLNd    ^Öâ)*.°dONLNd    `(<4[(PZNote:°dONLNd    f(`4‚)$While it is perfectly legal °dONLNd    Ç(‚4⁄)Ç/to have 'FOND's continue to reference the older°dONLNd    ≤4`@˝(\~'FONT' type, DTS recommends °dONLNd    Œ4˝@⁄)ù)that you avoid 'FONT's. Accessing 'FONT's°dONLNd    ¯@`LÍ(h~is much slower, since the °dONLNd
  2329. @ÍL⁄)ä)Font Manager always looks for 'FOND's and°dONLNd
  2330. <L`XΔ(t~'NFNT's first. More °dONLNd
  2331. PLΔX⁄)f8importantly, 'FONT's are troublemakers if an application°dONLNd
  2332. âX`dP(Ä~.comes with its own font in its resource fork. °dONLNd
  2333. ∑XPd⁄)Imagine an application that°dONLNd
  2334. ”d`pµ(å~Dincludes a private 'FOND' which references a 'FONT' in its resource °dONLNd dµp⁄(å”fork by°dONLNd p`|9(ò~)resource ID. When the Font Manager wants °dONLNd Hp9|⁄)Ÿ#to load the font resource, it first°dONLNd l|`àé(§~
  2335. looks for °dONLNd v|éà⁄).Ca resource of type 'NFNT' with this same resource ID. If there’s an°dONLNd ∫à`îl(∞~5'NFNT' in the System file with the same resource ID, °dONLNd Ôàlî⁄(∞äthe Font Manager will°dONLNd î`†ü(º~>pick it instead of the 'FONT' from the application’s resource °dONLNd Cîü†⁄(ºΩ fork.  This°dONLNd O†`¨2(»~,happens more often than you’d like to think! ◊X◊
  2336. (ÏZ
  2337. Fond of FONDs(Ïˇ3) of 12ˇfi◊#ˇ ˇˇˇˇ#◊ 
  2338. IR,Times
  2339. .+6-Macintosh Technical Notes /4/˘
  2340. °dONLNd+*7.+&•°dONLNd+77Â)
  2341. %Under the current font architecture, °dONLNd'+Â7∂)Æ)the font name is the resource name of the,
  2342. Courier°dONLNdQ77Ca(`U'FOND'°dONLNdW8aDÊ)* resource (let’s forget about °dONLNdu7ÊC)Ö'FONT'°dONLNd{8DQ)*s altogether), °dONLNdä8QD∂)Aso the font name can°dONLNdüD7Pä(lUJbe any Pascal string. Unfortunately, this conflicts with the 31-character °dONLNdÈDäP∂(l®
  2343. limitation°dONLNdÙP7\(xU0of a file name when the System 7 Finder derives °dONLNd$P\∂)Áthe file name of a movable font°dONLNdD\7hI(ÑUfile °dONLNdI\IhM)(°dONLNdJ\Mhü)Inside Macintosh°dONLNdZ\üh≤)R5 Volume VI, page 9-34) from the font name. Some third°dONLNdè\≤h∂(Ñ–-°dONLNdêh7tâ(êUparty fonts come °dONLNd°hât∂)R;with font names long enough to cause trouble.  You may also°dONLNd›t7Ä(úU'see this problem when trying to open a °dONLNdtÄ∂) %suitcase if the Finder can't generate°dONLNd*Ä7åÚ(®U+distinct names for all of the fonts in the °dONLNdUÄÚå∂)ª)suitcase; the Finder may say the suitcase°dONLNdå7òΩ(¥Uis “damaged” when it is not.°dONLNdú§∞7(Ã6Note:°dONLNd¢§<∞f)$;Each TrueType 'sfnt' resource contains a Naming Table (see °dONLNd›§f∞∂(ÃÑ
  2344. The TrueType™°dONLNdÎ∞<ºø(ÿZFont Format Specification°dONLNd∞øº )É, °dONLNd∞ º∂) &APDA™ M0825LL/A) which provides nearly°dONLNd-º<»î(‰Zunrestricted font °dONLNd?ºî»∂)X5naming capabilities, to accommodate the needs of font°dONLNdu»<‘(Z'manufacturers. A forthcoming Macintosh °dONLNdú»‘∂)Δ!Technical Note on TrueType Naming°dONLNdæ‘<‡Ê(¸Z$Tables gives additional information.°dONLNd„Ï*¯.(H•°dONLNdÂÏ7¯&)
  2345. /QuickDraw and the current Font Manager have no °dONLNdÏ&¯∂)Ô provision for stylistic variants°dONLNd5¯7#( U1like “light,” “medium,” “demi,” “book,” “black,” °dONLNdf¯#∂)Ï “heavy,” “extra,” “ultra,” etc.,°dONLNdá7ü(,Uused in the context of °dONLNdûü∂)h;professional typesetting. Therefore, each of these variants°dONLNd⁄7m(8UAcomes with a separate font family resource. Probably for reasons °dONLNdm∂(8ãof consistency,°dONLNd+7(‹(DU%the “italic” variants have their own °dONLNdP‹(∂)•-font family resources as well. Unfortunately,°dONLNd~)75t(QU unless each °dONLNdä(t4û)='FOND'°dONLNdê)û5T)*% references both the “plain” and the °dONLNdµ)T5∂)∂“italic” font strikes,°dONLNdÃ57A~(]UEQuickDraw will no longer know a customized italic font strike exists.°dONLNdM7Yè*JIt is fairly easy, using System 7 and ResEdit, to merge two font families °dONLNd]MèY∂(u≠(named,°dONLNdeY7e¿(ÅUfor exmaple, “myFont” and °dONLNdY¿e∂)â/“myFont italic”) into one.  This way, QuickDraw°dONLNdØe7q'(çU4will automatically use the pre-designed italic font °dONLNd„e'q∂)strike instead of creating one°dONLNdq7}(ôU0algorithmically.  Follow these convenient steps:°dONLNd4ä*ñ4(≤H1.°dONLNd7ä<ñô)Make sure there is °dONLNdJäôñO)]$no resource ID conflict between the °dONLNdnâOïy)∂'NFNT'°dONLNdtäyñô)*s and °dONLNdzâôï√) 'sfnt'°dONLNdÄä√ñ»)*s°dONLNdÇñ<¢ª(æZbelonging to both families.°dONLNdû¢*Æ4( H2.°dONLNd°¢<Æ),Make sure the style bits for italic are set °dONLNdբƻ)Δ(in the font association table of “myFont°dONLNdˆÆ<∫[(÷Zitalic.”°dONLNdˇª*«4(„H3.°dONLNdª<«é)From ResEdit’s °dONLNdªé«l)R)File menu, “Get Info...” on the “myFont” °dONLNd:∫lΔñ)fi'FOND'°dONLNd@ªñ«»)*
  2346.  resource.°dONLNdL»<‘(Z+Write down the resource ID of the “myFont” °dONLNdw«”<)÷'FOND'°dONLNd}»<‘@)*.°dONLNd’*·4(˝H4.°dONLNdÇ’<·!)/From ResEdit’s File menu, “Get Info...” on the °dONLNd±’!·n)“myFont italic” °dONLNd¡‘n‡ò)M'FOND'°dONLNd«’ò·»)*    .  Change°dONLNd—·<ÌÌ(    Z'its resource ID to be identical to the °dONLNd¯·ÌÌ»)±)one you wrote down in step 3.  Change its°dONLNd    "Ì<˘¬(Zresource name to “myFont.”°dONLNd    =˘*4(!H5.°dONLNd    @˘<ç)GUse the Finder in System 7 to move the contents of the “myFont italic” °dONLNd    á˘ç»(!´
  2347. suitcase into°dONLNd    ï<(-Z#the original “myFont” suitcase. It °dONLNd    ∏»)¥)will merge all constituents into one font°dONLNd    ‚<u(9Z association °dONLNd    Óu»)9Etable, and thus enable transparent substitution of the right font for°dONLNd
  2348. 4<)±(EZQuickDraw’s italic style.
  2349. °dONLNd
  2350. NAPå(l6Version Numbers
  2351. °dONLNd
  2352. ^\hö*The 'FOND' structure (see °dONLNd
  2353. x\öhÎ)ÇInside Macintosh°dONLNd
  2354. à\Îh)Q Volume °dONLNd
  2355. ê\h⁄)+'IV, page 45, “FamRec”) contains a field°dONLNd
  2356. ∏ht&(ê66ffVersion, and inquiring minds naturally want to know °dONLNd
  2357. Óh&t⁄(êD$more about it. Before anything else,°dONLNd tÄÙ(ú6.however, please read the following disclaimer: ◊4◊˘
  2358. *P4) of 12(Ï∑
  2359. Fond of FONDsˇä◊#ˇ ˇˇˇˇ#◊ 
  2360. IR,Times
  2361. .+Z-Developer Support Center(-ÛMay 1992 /X/
  2362. °dONLNd<)|(EZ Disclaimer:°dONLNd Ñ)é)H3The Font Manager does not check version numbers in °dONLNd?é)⁄(E¨
  2363. a 'FOND', and°dONLNdM)Ñ5¯(Q¢we recommend that you °dONLNdc)¯5⁄)t0not rely on the (intentionally vague) statements°dONLNdî5ÑA∞(]¢>below, but rather analyze the data in the 'FOND'independently.°dONLNd”M<Yó(uZCurrently, values °dONLNdÂMóY˛)[D0...3 may appear in the ffVersion field, with the following intended°dONLNd*Y<eÇ(ÅZinterpretations:°dONLNd;q<}m*
  2364. Version 0:°dONLNdFq{}¯)?Usually indicates that the °dONLNdaq¯}˛)}1'FOND' has been created on the fly by the Font/DA°dONLNdì}{â,(•ô$Mover (or the System 7 Finder). But °dONLNd∑},â˛)±+the 'FOND' for Palatino on the distribution°dONLNd„â{ï4(±ô&disks of System 7 is a counterexample.°dONLNd
  2365. ï<°m(ΩZ
  2366. Version 1:°dONLNdï{°Ï)?Obviously indicates the °dONLNd-ïϰ¨)q%first version when 'FOND's came out (°dONLNdR侮˛)¿Inside Macintosh°dONLNdc°{≠„(…ôVolume IV, page 36).°dONLNdx≠<πm(’Z
  2367. Version 2:°dONLNdÉ≠{πÕ)?Corresponds to °dONLNdí≠Õπ·)R1the extension of the 'FOND' format documented in °dONLNd√≠·π˛(’ˇInside°dONLNd π{≈¨(·ô    Macintosh°dONLNd”π¨≈Ø)1 °dONLNd‘πØ≈˛)@Volume V, page 185 (which does not mean that the 'FOND' actually°dONLNd≈{—(Ìôcontains a bounding box table).°dONLNd5—<›m(˘Z
  2368. Version 3:°dONLNd@—{›é)?7The 'FOND' is supposed to contain a bounding box table.°dONLNdxÈ<ıT(ZThis °dONLNd}ÈTı˛)Xbrings up an annoying fact.  All measurement values (referring to a hypothetical 1-point°dONLNd÷ı<‚(Z$font) in the 'FOND' are in a 16-bit °dONLNd˙ı‚˛)¶<fixed-point format, with an integer part in the high-order 4°dONLNd7<
  2369. ∞()Zbits and a fractional part °dONLNdR∞
  2370. ˛)tEin the low-order 12 bits. You would expect that negative values (like°dONLNdò
  2371. <ö(5Zfor ffDescent, or in °dONLNd≠
  2372. ö˛)^Ithe kerning tables) are represented in the usual two’s-complement format,°dONLNd˜<%m(AZ
  2373. such that °dONLNdm%˛)1Ostandard binary arithmetic applies. This is mostly true, but not always. Again,°dONLNdQ%<1N(MZ8Palatino is a counterexample (and probably not the only °dONLNdâ%N1˛(Ml!one). To our knowledge, version 0°dONLNd´1<=Õ(YZRand version 1 'FOND's have negative values represented in a format where the most °dONLNd˝1Õ=˛(YÎ significant°dONLNd    =<I (eZ"bit is the sign bit, and the rest °dONLNd+= I˛)é@represents the absolute value.  However, there is nothing in the°dONLNdlI<Ut(qZAsystem software that enforces this, so counterexamples may exist.°dONLNdÆa<mp*Warning:°dONLNd∑aÑmH)H&Don’t rely on the version number, but °dONLNd›aHm⁄)ƒinclude sanity checks for the°dONLNd˚mÑyØ(   negative °dONLNdmØy⁄)+:values in a 'FOND' instead!  The following Pascal function°dONLNd?yÑÖ
  2374. (°¢shows how this can be done:,
  2375. Courier
  2376.     °dONLNd[è<ö1(∂Z1    FUNCTION Check4p12Value(n: Integer): Integer;°dONLNdçô<§≥*
  2377. K    { n is a 4.12 fixed-point value; i.e., its "real" value is n/4096.    }°dONLNdŸ£<Æ≥*
  2378. K    { If n is "unreasonably negative," interpret the most significant bit }°dONLNd%≠<∏≥*
  2379. K    { as sign bit, and convert to the usual two's complement format.      }°dONLNdq¡<Ãx*        BEGIN°dONLNd~À<÷¬*
  2380. N          IF n < $8FFF THEN { means: (4.12-interpretation of n) is below - 7 }°dONLNdÕ’<‡,*
  2381. 0             Check4p12Value := - BitAnd(n,$7FFF)°dONLNd˛fl<Íï*
  2382. E         { i.e., mask sign bit, and take negative of absolute value }°dONLNd    DÈ<ÙÇ*
  2383.           ELSE°dONLNd    SÛ<˛·*
  2384. !             Check4p12Value := n;°dONLNd    u˝<s*
  2385.        END;
  2386. °dONLNd    Å<.*& In the Heart of the Font Manager
  2387. °dONLNd    ¢:<Fò*Swapping Fonts°dONLNd    ±R<^|*
  2388. As stated in °dONLNd    æR|^ÿ)@Inside Macintosh, °dONLNd    –Rÿ^‘)\0there is only one contact between QuickDraw and °dONLNd
  2389. R‘^˛)¸the Font°dONLNd
  2390.     ^<j(ÜZ*Manager: the FMSwapFont function. Each of °dONLNd
  2391. 3^jú)‡the three QuickDraw text °dONLNd
  2392. L^újÕ)Ä    measuring°dONLNd
  2393. U^Õj˛)1
  2394.  functions°dONLNd
  2395. `j<v~(íZ (CharWidth, °dONLNd
  2396. lj~v˛)BEStringWidth and TextWidth) always ends up in the QuickDraw bottleneck°dONLNd
  2397. ≤v<Çõ(ûZ?procedure QDProcs.txMeasProc. Each of the three QuickDraw text °dONLNd
  2398. ÒvõǬ(ûπdrawing°dONLNd
  2399. ¯v¬Ç˛)'  procedures°dONLNd Ç<é`(™Z7(DrawChar, DrawString and DrawText)  always ends up in °dONLNd ;Ç`é˛(™~the QDProcs.textProc bottleneck°dONLNd [é<ö8(∂Z2procedure. Any reasonable textProc (like StdText) °dONLNd çé8ö˛)¸*needs to call the currently-installed text°dONLNd ∏ö<¶œ(¬ZLmeasuring bottleneck procedure before actually rendering the text. And what °dONLNd öœ¶˛(¬Ìdoes any ◊X◊
  2400. (ÏZ
  2401. Fond of FONDs(Ïˇ5) of 12ˇ ◊#ˇ ˇˇˇˇ#◊ 
  2402. IR,Times
  2403. .+6-Macintosh Technical Notes /4/˘
  2404. °dONLNd+ñ*Preasonable text measuring bottleneck procedure(like StdTxMeas) do first, before °dONLNdPñ+⁄(G¥anything else?°dONLNd_+7É(S6It calls FMSwapFont, °dONLNdt+É7⁄)kHto make sure we are talking about the right font and its properties! (To°dONLNdΩ7C§(_6be precise, GetFontInfo and °dONLNdŸ7§C⁄)å@FontMetrics are the other calls that make sure the right font is°dONLNdCOâ(k6Lswapped in and set up, without requiring you to call FMSwapFont explicitly.)°dONLNdg[gÆ* Responding to a font request is °dONLNdá[Æg⁄)ñ:a lot of work, and FMSwapFont has been optimized to return°dONLNd¬gs˘(è62as quickly as possible if the request is the same °dONLNdÙg˘s⁄)·.as the previous one. Building the global width°dONLNd#sI(õ6 table (see °dONLNd.sIj)1Inside °dONLNd5sjõ)!    Macintosh°dONLNd>sõ⁄)1; Volume IV, page 41) is among the more time-consuming tasks°dONLNdzã˜(ß6,related to FMSwapFont; this is why the Font °dONLNd¶˜ã⁄)fl+Manager maintains a cache of up to 12 width°dONLNd“ãó7(≥6tables.°dONLNd⁄£Øi*Inside Macintosh°dONLNdÍ£iØæ)QD Volume I, page 220 documents the Font Manager’s choice when a font °dONLNd.£æØ⁄(À‹of the°dONLNd5تπ(◊6"requested size is not available.  °dONLNdWØπª⁄)°6However, some consequences or additional features have°dONLNd骫>(„6?occasionally been a surprise to developers (and users as well).°dONLNdŒ”fl*)Scaling Factors in FMOutPut and StdTxMeas°dONLNd¯Î˜x*Let’s suppose you °dONLNd
  2405. Îx˜⁄)`Chave only a 12-point bitmap version of Palatino, and don’t have any°dONLNdN˜¢(6Palatino outline fonts. When °dONLNdk˜¢⁄)ä=you request Palatino 18, QuickDraw sets up the FMInput record°dONLNd©‹(+6#with size = 18 and numer = denom = °dONLNdË⁄)ƒ/Point($00010001).On return, the FMOutput record°dONLNd¸ó(76contains the handle to the °dONLNdó⁄)?font record to use (the 'NFNT' with the Palatino 12 bitmap font°dONLNdW'g(C6Istrike), and indicates the scaling factors QuickDraw will have to use to °dONLNd†g'⁄(CÖproduce the desired text°dONLNdπ'3≥(O6Tpoint size in FMOutput.numer and FMOutput.denom. In this example, that ratio is 3/2.°dONLNd?Kç*LNote that these are also the values returned in StdTxMeas (Inside Macintosh °dONLNdZ?çK⁄(g´Volume I, page°dONLNdiKWg(s6199) if you call °dONLNdzKgW⁄)OCthe procedure with numer = denom = Point($00010001).  Why?  Because°dONLNdæWcø(6StdTxMeas calls FMSwapFont, as °dONLNd›Wøc»)ß2explained under “Swapping Fonts.”  StdTxMeas does °dONLNdW»c⁄(Ênot°dONLNdco5(ã6apply °dONLNdc5o⁄)Xthese scaling factors to the text it measures. In our example, it would measure Palatino°dONLNdro{Ø(ó612 and return numer and denom°dONLNdèoØ{≤)ó °dONLNdêo≤{Í) in the ratio °dONLNdûoÍ{⁄)833/2 to tell you that your application must multiply°dONLNd“{á-(£6<the results by these values to get the correct measurements °dONLNd{-á⁄(£K$for Palatino 18.  This has surprised°dONLNd3áì|(Ø6Emore than one programmer who didn’t expect numer and denom to change!°dONLNdyü´:*;By the way, the Font Manager always normalizes the scaling °dONLNd¥ü:´⁄(«X factors as fractions numer/denom°dONLNd’´∑r(”6Esuch that the denominator is equal to 256.  In our example, the real °dONLNd    ´r∑⁄(”ênumbers returned by°dONLNd    .∑√K(fl68FMSwapFont or StdTxMeas are numer = 384 and denom = 256.°dONLNd    gœ€L*Warning:°dONLNd    pœ`€ë)H<If the scaling factors numer and denom passed to StdTxMeas, °dONLNd    ¨œë€∂(˜ØStdText°dONLNd    ¥€`Áv(~(see °dONLNd    π€vÁ«)Inside Macintosh°dONLNd    …€«Áz)Q% Volume I, pages 198 and 199), or in °dONLNd    Ó€zÁ∂)≥ the FMInput°dONLNd    ˙Á`Ûè(~
  2406. record to °dONLNd
  2407. ÁèÛ∂)/7FMSwapFont are such that txSize*numer.v/denom.v is less°dONLNd
  2408. <Û`ˇw(~than °dONLNd
  2409. AÛwˇ∂)B0.5 and rounds to 0, and if there is more than one 'sfnt' resource°dONLNd
  2410. Ñˇ` 9('~/referenced in the font association table, then °dONLNd
  2411. ≥ˇ9 ∂)Ÿthe current Font Manager°dONLNd
  2412. Ã `É(3~>may get confused and return results for the wrong font strike.°dONLNd #/Í(K6"TrueType Always Has the Right Size°dONLNd .;Gy*The default value of °dONLNd C;yG⁄)aGoutlinePreferred is FALSE. If you have bitmap fonts for Palatino 12 and°dONLNd ãGS–(o6^Palatino 14 in your system as well as a Palatino TrueType font, then requests for Palatino 12 °dONLNd ÈG–S⁄(oÓor°dONLNd ÏS_({65Palatino 14 are fulfilled with the bitmap fonts, but °dONLNd !S_⁄)Ó.requests for any other size are fulfilled with°dONLNd P_kƒ(á6%the TrueType font. In particular, if °dONLNd u_ƒk⁄)¨8you (or, for example, a printer driver) need Palatino 12°dONLNd ÆkwC(ì6>scaled by 2, the Font Manager will actually look for Palatino °dONLNd ÏkCw⁄(ìa24 and return the outline font,°dONLNd
  2413. wÉô(ü6regardless of the setting of°dONLNd
  2414. (wôÉù)Å °dONLNd
  2415. )wùɰ)5outlinePreferred. Even if you wanted the bitmap font °dONLNd
  2416. ^w°É⁄(üø doubled for°dONLNd
  2417. jÉè7(´6exact °dONLNd
  2418. pÉ7è⁄)M“what-you-see-is-what-you-get” text placement, you’re out of luck—you get the°dONLNd
  2419. æèõè(∑6NTrueType font, which may have very different font metrics or character shapes. ◊4◊˘
  2420. *56) of 12(Ï∑
  2421. Fond of FONDsˇÊ◊#ˇ ˇˇˇˇ#◊ 
  2422. IR,Times
  2423. .+Z-Developer Support Center(-ÛMay 1992 /X/
  2424. °dONLNd<)G(EZIf °dONLNdG)˛) ]the Font Manager uses an outline font to fulfill a given font request, the IsOutline function°dONLNda)<5Δ(QZOreturns TRUE. Interestingly, this does not imply that RealFont returns TRUE as °dONLNd∞)Δ5˛(Q‰ well. If the°dONLNdΩ5<Ag(]Z=text size is smaller than the value lowestRecPPEM (“smallest °dONLNd˙5gA˛(]Ö readable size in pixels”) in the°dONLNdA<M(iZ-'head' font header in the TrueType font (see °dONLNdHAM$)”The °dONLNdLA$M”)"TrueType Font Format Specification°dONLNdnA”M˛)Ø    , version°dONLNdxM<Y(uZ-1.0, page 227),  then RealFont returns FALSE!°dONLNd¶e<qt*5First Size, Then Style—or: To Be or Not to Be Outline°dONLNd‹}<â˜*%When the Font Manager walks the font °dONLNd}˜â˛)ª7association table of a 'FOND' to look for a font strike°dONLNd9â<ïß(±Zof a specified size and °dONLNdQâßï˛)kLstyle, it stops at the first font of the right size. Only if you requested a°dONLNdûï<°˜(ΩZcstylistic variant (like bold or italic) does it take a closer look at the fonts of the same size.  °dONLNd˛(ΩIt°dONLNd°<≠(…Zadoes this by putting weights on the various style bits (for example, 8 for italic, 4 for bold, 3 °dONLNde°≠˛(…for°dONLNdi≠<π‚(’ZYoutline) and choosing the font strike whose style weight most closely matches the weight °dONLNd¬≠‚π˛(’of the°dONLNd…π<≈ù(·Zrequested style. All °dONLNdfiπù≈˛)aGthis is fine when only bitmap fonts are available. With the presence of°dONLNd&≈<—Ã(ÌZTrueType outlines, however, °dONLNdB≈ײ)ê=the results are not always as expected, depending on the font°dONLNdÄ—<›©(˘Zconfiguration installed.°dONLNdöÈ<ıΔ*Let’s look at a few examples:°dONLNd∏<
  2425. {*
  2426. Example 1:°dONLNd√ç
  2427. y)Q0Let’s suppose you have the bitmap font Times 12 °dONLNdÛy
  2428. ˛)Ï(Normal) and the TrueType°dONLNd
  2429. 
  2430. çp(5´-fonts Times (Normal), Times Italic and Times °dONLNd:
  2431. p˛)„Bold in your system. If you°dONLNdVç%˚(A´request Times 14 Italic °dONLNdn˚%˛)n5or Times 14 Bold, it’s rendered from the Times Italic°dONLNd§%ç1Ù(M´Gor Times Bold TrueType fonts.  However, if you ask for Times 12 Italic °dONLNdÎ%Ù1˛(Mor°dONLNdÓ1ç=(Y´Times 12 Bold, and your °dONLNd1=˛)z4system has the default setting of outlinePreferred =°dONLNd;=çI¥(e´5FALSE, the Font Manager decides to take the Times 12 °dONLNdp=¥I˛(e“bitmap and let°dONLNdIçUœ(q´HQuickDraw algorithmically slant it (for italics) or smear it (for bold).°dONLNd a<m{(âZ
  2432. Example 2:°dONLNd’açm®)QLet’s °dONLNd€a®m˛)Esuppose you want to draw big, bold Helvetica characters and there are°dONLNd!mçyÔ(ï´no existing bitmaps °dONLNd5mÔy˛)b5for the size you want. If the Helvetica Bold TrueType°dONLNdkyçÖı(°´Loutlines are available, the Font Manager chooses them and the only surprise °dONLNd∑yıÖ˛(°in°dONLNd∫Öçë—(≠´text rendering °dONLNd…Ö—ë˛)D>will be a pleasant one. If there is no Helvetica Bold TrueType°dONLNdëçù(π´font, however (like in the °dONLNd#ëù˛)Ö+machine of your customer, who kept only the°dONLNdOùç©Ê(≈´normal Helvetica °dONLNd`ùÊ©˛)Y5TrueType font in his system), then the characters are°dONLNdñ©çµù(—´2rendered using the normal Helvetica outlines and, °dONLNd»©ùµ˛(—ªin a second step,°dONLNd⁄µç¡‘(›´@QuickDraw applies its horizontal 1-pixel “smearing” to simulate °dONLNd    µ‘¡˛(›Úthe bold°dONLNd    #¡çÕ,(È´!stylistic variant. The result is °dONLNd    D¡,Õ˛)ü(very different (and rather an unpleasant°dONLNd    mÕ矪(ı´
  2433. surprise).°dONLNd    xÂ<Ò{(
  2434. Z
  2435. Example 3:°dONLNd    ÉÂçÒ/)Q%Admittedly, this is less likely (but °dONLNd    ®Â/Ò˛)¢(it has happened). Let’s suppose somebody°dONLNd    —Òç˝È(´Hdecides to rip the Times TrueType outline out of the System file (don’t °dONLNd
  2436. ÒÈ˝˛( ask°dONLNd
  2437. ˝ç    fi(%´Dme why—I don’t  know). He forgets to take the Times Italic TrueType °dONLNd
  2438. b˝fi    ˛(%¸outline°dONLNd
  2439. j    ç¡(1´=away as well. The next time he draws text in Times (Normal), °dONLNd
  2440. ß    ¡˛(1fl
  2441. in a size for°dONLNd
  2442. µç!(=´which there is no bitmap °dONLNd
  2443. Œ!˛)Å.font (or if outlinePreferred = TRUE), the Font°dONLNd
  2444. ˝!ç-à(I´5Manager goes for an 'sfnt', and the text shows up in °dONLNd 2!à-û)˚italic°dONLNd 8!û-¸)  (what a surprise!).°dONLNd N9<Eâ(aZEUnfortunately, given the current implementation of the Font Manager, °dONLNd ì9âE˛(aßthere are no solutions to°dONLNd ≠E<Q(mZ%the problems illustrated above—other °dONLNd “EQ˛)¥:than asking users of your application to install the fonts°dONLNd
  2445. Q<]‚(yZyou recommend. The only way °dONLNd )Q‚]˛)¶8to anticipate these potential surprises from within your°dONLNd b]<i(ÖZTapplication is to look into the 'FOND's font association table. You can’t depend on °dONLNd ∂]i˛(Öthe°dONLNd ∫i<u (ëZ+IsOutline function because it returns TRUE °dONLNd Âi u˛)œ2as soon as the Font Manager stops at an 'sfnt', in°dONLNd
  2446. u<Åi(ùZ@its first pass through the font association table—regardless of °dONLNd
  2447. XuiŞ(ùá subsequent stylistic variations.°dONLNd
  2448. zÅ<çÂ(©ZWThis means, for example, if you ask for Helvetica Bold and IsOutline returns TRUE, you °dONLNd
  2449. —ÅÂç˛(©don’t°dONLNd
  2450. ◊ç<ôN(µZ7know if you got the Helvetica Bold TrueType font or if °dONLNdçNô˛(µl!QuickDraw “smeared” the Helvetica°dONLNd0ô<•ß(¡Z(Plain) TrueType font. ◊X◊
  2451. *+
  2452. Fond of FONDs(Ïˇ7) of 12ˇ◊#ˇ ˇˇˇˇ#◊ 
  2453. IR,Times
  2454. .+6-Macintosh Technical Notes /4/˘
  2455. °dONLNd7F*5Where Do the Widths Come From?
  2456. °dONLNdR^7*;Text measuring (for example, for precise text placement in °dONLNdZR7^⁄(zUforms with bounding boxes) and°dONLNdy^j—(Ü6^most line layout algorithms for justified text rely heavily on the character widths contained °dONLNd◊^—j⁄(ÜÔin°dONLNd⁄jv (í65the global width table. Given that under the current °dONLNdj v⁄)Û+font architecture, we may easily have three°dONLNd;vÇL(û6?or more different width tables for the same font specification °dONLNdzvLÇ⁄(ûj(the non-proportional integer°dONLNdòÇéÅ(™6Fwidths attached to the 'NFNT', the fractional widths contained in the °dONLNdfiÇÅé⁄(™ü'FOND', and the°dONLNdÓéö¶(∂6fractional widths provided by °dONLNd é¶ö⁄)é@the 'sfnt'), it is important to understand where the widths come°dONLNdMö¶j(¬6from in any case.°dONLNd_≤æ“*%Since SetFractEnable was introduced (°dONLNdÑ≤“æ$)∫Inside Macintosh°dONLNdî≤$æ§)R Volume IV, page 32 and °dONLNd¨≤§æ⁄)Ä    Volume V,°dONLNd∂æ b(Ê6page 180), its °dONLNd≈æb ⁄)JGsetting TRUE or FALSE was supposed to give predictable effects. If it’s°dONLNd
  2457.  ÷¶(Ú6PFALSE, the Font Manager takes the integer widths from the 'NFNT'; if it’s TRUE, °dONLNd] ¶÷⁄(Úƒ it takes the°dONLNdj÷‚±(˛6Tfractional widths from the 'FOND'. Unfortunately, there are some additional details °dONLNdæ÷±‚⁄(˛œand side°dONLNd«‚Ó≠(
  2458. 6 effects that are not well known.°dONLNdË˚*•°dONLNdÍ˚%≈)
  2459. !The Font Manager looks at bit 14 °dONLNd ˚≈C)†of the ffFlags field in the ,
  2460. Courier°dONLNd'˙Cm)~'FOND'°dONLNd-˚mà)* (see °dONLNd3˚à⁄)Inside Macintosh°dONLNdD%Ã(/C^Volume IV pages 36 and 37). If it is set (like it is for Courier), the fractional widths from °dONLNd¢Ã⁄(/Íthe°dONLNd¶%O(<C'FOND'°dONLNd¨O c)* are °dONLNd±c })never°dONLNd∂} ù)  used.°dONLNdæ ,(H6•°dONLNd¿ %,z)
  2461. If SetFractEnable °dONLNd“ z,⁄)UKis TRUE and you request a stylistic variation like bold or italic, the Font°dONLNd,%8Ã(TC#Manager looks at bits 12 and 13 of °dONLNdA,Ã8⁄)ß9the ffFlags field to decide how different widths or extra°dONLNd{8%DW(`CDwidths for the stylistic variants have to be used.  What it decides °dONLNdø8WD⁄(`uis documented in the “Font°dONLNd⁄D%Pà(lCManager” chapter of °dONLNdÓDàP)cInside Macintosh Preview°dONLNdDPN){, located on the °dONLNdDNP±)KDeveloper CD Series°dONLNd*D±P–)c discs.°dONLNd2P\(x6•°dONLNd4P%\:)
  2462. =Given that it is not possible to set the pen to a fractional °dONLNdqP:\⁄(xX"position, precise text positioning°dONLNdî\%h/(ÑC5with fractional widths enabled is always compromised °dONLNd…\/h⁄(ÑM!because of (accumulated) rounding°dONLNdÎh%tE(êCerrors.°dONLNdÛtÄ(ú6•°dONLNdıt%Äê)
  2463. HQuickDraw distributes the accumulated rounding errors across characters °dONLNd=têÄ⁄(úÆwithin a string°dONLNdMÄ%åe(®CE(instead of adding it at the end of the drawn text). This results in °dONLNdíÄeå⁄(®Époor text quality on the°dONLNd´å%ò(¥C-screen, and in problems when calculating the °dONLNdÿåò⁄)Ï'position of the insertion point between°dONLNdò%§X(¿C characters.°dONLNd §∞(Ã6•°dONLNd§%∞ù)
  2464. The LaserWriter driver °dONLNd%§ù∞⁄)x8watches what you pass to SetFractEnable. Passing TRUE to°dONLNd^∞%º5(ÿC9SetFractEnable disables some of the LaserWriter driver’s °dONLNdó∞5º⁄(ÿS#line layout features, assuming that°dONLNdªº%»H(‰C;the programmer intends to control text placement manually. °dONLNdˆºH»⁄(‰f Explicitly passing FALSE to°dONLNd    »%‘û(CSetFractEnable achieves °dONLNd    +»û‘⁄)y<different results than using the default value of FALSE—Font°dONLNd    h‘%‡ä(¸CSubstitution behaves °dONLNd    }‘ä‡⁄)eCdifferently, for example.  These effects are sometimes Not What You°dONLNd    ¡‡%ÏM(CWanted.°dONLNd    …ϯ(6•°dONLNd    ÀÏ%¯;)
  2465. 7On non-32-Bit-QuickDraw systems, SetFractEnable is not °dONLNd
  2466. Ï;¯⁄(Y"recorded in pictures. This affects°dONLNd
  2467. %¯%p( Cthe line layout °dONLNd
  2468. 5¯p⁄)KFof text reproduced through DrawPicture if the picture was created with°dONLNd
  2469. |%ü(,Cfractional widths enabled.°dONLNd
  2470. ó(!(D66In systems with TrueType, quite naturally  the widths °dONLNd
  2471. Õ!(F(D?always °dONLNd
  2472. ‘F(Ã)%come from the 'sfnt' when °dONLNd
  2473. ÓÃ(⁄)Üthe°dONLNd
  2474. Ú(4(P63Font Manager uses a TrueType font.  If fractEnable °dONLNd %(4⁄)ˇ&is FALSE, hand-tuned integer character°dONLNd L4@“(\6Zwidths for specific point sizes come from the 'hdmx' table in the 'sfnt'.  If fractEnable °dONLNd ¶4“@⁄(\is°dONLNd ©@LS(h6
  2475. FALSE and °dONLNd ≥@SL⁄);Tno 'hdmx' table is present or it contains no entries for the desired point size, the°dONLNd LXn(t6Kfractional character widths from the 'sfnt' are rounded to integral values.°dONLNd Tdp∂*More Line Layout Problems°dONLNd n|àõ*The routines SpaceExtra (°dONLNd á|õàÔ)ÉInside Macintosh°dONLNd ó|Ôàı)T °dONLNd ò|ıàΩ)#Volume I, page 172) and CharExtra (°dONLNd ª|Ωà⁄)»Inside°dONLNd ¬àîM(∞6
  2476. Macintosh °dONLNd ÃàMîv)5Volume °dONLNd ”àvî⁄))GV, page 77; available only in color GrafPorts) are intended to help you°dONLNd
  2477. î†(º62draw fully justified text. This works fine on the °dONLNd
  2478. Mî†⁄)Ï-screen, but not all printer drivers are smart°dONLNd
  2479. {†¨^(»6Denough to use these settings appropriately under all circumstances. °dONLNd
  2480. ø†^¨⁄(»|In particular, if you pass ◊4◊˘
  2481. (Ï68) of 12(Ï∑
  2482. Fond of FONDsˇÊ◊#ˇ ˇˇˇˇ#◊ 
  2483. IR,Times
  2484. .+Z-Developer Support Center(-ÛMay 1992 /X/
  2485. °dONLNd<)∏(EZTRUE to SetFractEnable, °dONLNd∏)˛)|Eor if you turn the LaserWriter driver’s line layout algorithm off (by°dONLNd^)<5–(QZOmeans of the picture comment LineLayoutOff; see Macintosh Technical Note #91), °dONLNd≠)–5˛(QÓ
  2486. or if font°dONLNd∏5<A:(]Z:substitution is enabled and actually occurs, it is better °dONLNdÚ5:A˛)˛'not to rely on SpaceExtra and CharExtra°dONLNdA<M•(iZPwhen printing fully justified text. Instead, keep the LaserWriter driver’s line °dONLNdjA•M˛(i√layout adjustments°dONLNd}M<Yu(uZ@off, and calculate the placement of your text (word by word, or °dONLNdΩMuY˛(uìeven character by character)°dONLNd⁄Y<eg(ÅZ    yourself.
  2487. °dONLNd‰}<å€*'Putting Text Into Boxes
  2488. °dONLNd¸ò<§ä*TrueType fonts °dONLNd ò䧲)NGcame to the Macintosh together with seven new Font Manager routines (as°dONLNdS§<∞à(ÃZdocumented in °dONLNda§à∞‡)LInside Macintosh °dONLNdr§‡∞˛)X6Volume VI, Chapter 12). The OutlineMetrics function is°dONLNd©∞<ºÑ(ÿZHcertainly the most sophisticated of these, and sample code illustrating °dONLNdÒ∞Ѻ˛(ÿ¢its usage may be helpful.°dONLNd º<»(‰Z(The following procedure DrawBoxedString °dONLNd3º»·)·$assumes that the new outline calls (°dONLNdWº·»˛)ƒInside°dONLNd^»<‘m(Z    Macintosh°dONLNdg»m‘∑)1B Volume VI, Chapter 12) are available, and that IsOutline returns °dONLNd©»∑‘˛(’ TRUE for the°dONLNd∂‘<‡ô(¸Zcurrent port setting.,
  2489. Courier
  2490.     °dONLNdÃÏ<˜,*0PROCEDURE DrawBoxedString(pt: Point; s: Str255);°dONLNd˝ˆ<Ã*
  2491. P{ Draw string s at pen position (pt.h, pt.v), and show each character's bounding°dONLNdN< Z*
  2492. box. }°dONLNdU<d*   CONST°dONLNd^<)æ*
  2493.       kOneOne = $00010001;°dONLNdy2<=Z*   VAR°dONLNdÄ<<G•*
  2494.       advA: FixedPtr;°dONLNdñF<Q•*
  2495.       lsbA: FixedPtr;°dONLNd¨P<[†*
  2496.       bdsA: RectPtr;°dONLNd¡Z<e*
  2497. -      err,i,yMin,yMax,leftEdge,temp: Integer;°dONLNdÔd<oπ*
  2498.       numer,denom: Point;°dONLNd    n<yπ*
  2499.       advance,lsb: Fixed;°dONLNd#x<ÉÇ*
  2500.       r: Rect;°dONLNd2å<ód*   BEGIN°dONLNd;ñ<°“*
  2501.       numer := Point(kOneOne);°dONLNdZ†<´Ω*
  2502. M      denom := Point(kOneOne); { unless you want to draw with scaling factors°dONLNd®™<µ˙*
  2503. &                                .... }°dONLNdœ¥<ø¥*
  2504.       MoveTo(pt.h,pt.v);°dONLNdËæ<…†*
  2505.       DrawString(s);°dONLNd˝»<”Ã*
  2506. P{ This is for the pleasure of your eyes only — in practice, you would probably }°dONLNdN“<›Ã*
  2507. P{ first look at the metrics, and then decide where and how to draw the string! }°dONLNdü‹<Á^*
  2508. :      advA := FixedPtr(NewPtr(Length(s) * SizeOf(Fixed)));°dONLNd⁄Ê<Ò^*
  2509. :      lsbA := FixedPtr(NewPtr(Length(s) * SizeOf(Fixed)));°dONLNd<˚T*
  2510. 8      bdsA := RectPtr(NewPtr(Length(s) * SizeOf(Rect)));°dONLNdN˙<"*
  2511. .      { Please, check for NIL pointers here! }°dONLNd}<∏*
  2512. L      err := OutlineMetrics(Length(s),@s[1],numer,denom,yMax,yMin,advA,lsbA,°dONLNd <Ê*
  2513. "                            bdsA);°dONLNdÌ<#õ*
  2514.       advance := 0;°dONLNd"<-O*
  2515. 7      FOR i := 1 TO Length(s) DO { for each character }°dONLNd9,<7Ç*
  2516.          BEGIN°dONLNdH6<A¬*
  2517. N         { Add accumulated advanceWidth and leftSideBearing of current glyph }°dONLNdó@<K*
  2518. ,         { horizontally to starting point. }°dONLNdƒJ<UJ*
  2519. 6         leftEdge := pt.h + Fix2Long(advance + lsbA^);°dONLNd˚T<_«*
  2520. O         r := bdsA^; { The bounding box rectangle is in TrueType coordinates. }°dONLNd    K^<ih*
  2521. <         temp := r.bottom; { need to flip it "upside down" }°dONLNd    àh<sÕ*
  2522.          r.bottom := - r.top;°dONLNd    ¶r<}π*
  2523.          r.top := - temp;°dONLNd    ¿|<áı*
  2524. %         OffsetRect(r,leftEdge,pt.v);°dONLNd    ÊÜ<ëh*
  2525. <         FrameRect(r); { This is the glyph's bounding box. }°dONLNd
  2526. #ê<õ*
  2527. $         advance := advance + advA^;°dONLNd
  2528. Hö<•Æ*
  2529. J         { "Advance" is Fixed, to avoid accumulation of rounding errors. } ◊X◊
  2530. *+
  2531. Fond of FONDs(Ïˇ9) of 12ˇT◊#ˇ ˇˇˇˇ#◊ 
  2532. IR,Times
  2533. .+6-Macintosh Technical Notes /4/˘,
  2534. Courier
  2535.     °dONLNd**/         { Now, bump pointers for next glyph. }°dONLNd0)4*
  2536. 4         bdsA := RectPtr(ord4(bdsA) + SizeOf(Rect));°dONLNde3>&*
  2537. 6         advA := FixedPtr(ord4(advA) + SizeOf(Fixed));°dONLNdú=H&*
  2538. 6         lsbA := FixedPtr(ord4(lsbA) + SizeOf(Fixed));°dONLNd”GRJ*
  2539.  
  2540.       END;°dONLNdfiQ\ü*
  2541.       DisposPtr(Ptr(advA));°dONLNd˙[fü*
  2542.       DisposPtr(Ptr(lsbA));°dONLNdepü*
  2543.       DisposPtr(Ptr(bdsA));°dONLNd2ozü*
  2544.    END; { DrawBoxedString }
  2545. °dONLNdNÖëa*OutlineMetrics °dONLNd]Öaë⁄)IJexists because many developers need pixel-precise information on placement°dONLNd®ëù`(π6
  2546. and bounding °dONLNdµë`ù⁄)HKboxes, often on a character-by-character basis.  Unfortunately, there is no°dONLNdù©º(≈6"similar facility for text drawing °dONLNd#ùº©⁄)§6with bitmap fonts. Worse, under certain circumstances,°dONLNdZ©µô(—6italicized or shadowed (or °dONLNdu©ôµ⁄)ÅAboth) bitmap fonts are sometimes poorly clipped, particularly for°dONLNd∑µ¡m(›6Gscaled sizes. Cosmetic workarounds include adding a space character to °dONLNd˛µm¡⁄(›ãstrings drawn in italic.°dONLNd¡Õa(È6EYou might also draw the text off-screen first (in order to determine °dONLNd]¡aÕ⁄(Èthe bounding box of the°dONLNduÕŸ´(ı6Sblack pixels) and use CopyBits to copy the text onto the screen—but using CopyBits °dONLNd»Õ´Ÿ⁄(ı… for text is°dONLNd‘ŸÂã(6usually bad for printing.°dONLNdÓÒ˝π*MThe existing documentation on the FMOutput and global width table structures °dONLNd;Òπ˝Ω(◊(°dONLNd<ÒΩ˝⁄)Inside°dONLNdC˝    M(%6
  2547. Macintosh °dONLNdM˝M    «)5Volume I, page 227 and °dONLNdd˝«    ⁄)z6Volume IV, page 41) suggests it’s possible to devise a°dONLNdõ    ´(16Qroutine for determining a fairly precise text bounding box for bitmap fonts. The °dONLNdÏ    ´⁄(1…    procedure°dONLNdˆ!?(=6below,  °dONLNd˛?!⁄)'SBitmapTextBoundingBox, is a first attempt. It assumes that TrueType is unavailable,°dONLNdR!-6(I6:or that the IsOutline call returned FALSE for the current °dONLNdå!6-⁄(IT!port settings. While the returned°dONLNdÆ-9ó(U6Nbounding box is not always “tight,” be careful before modifying the algorithm °dONLNd¸-ó9⁄(Uµ
  2548. and shrinking°dONLNd
  2549. 9EΩ(a6Wthe resulting bounding box—bitmap fonts just don’t  contain enough precise information °dONLNda9ΩE⁄(a€for an°dONLNdhEQä(m6Gexact bounding box, and different bitmap fonts and different sizes may °dONLNdØEäQ⁄(m®require different°dONLNd¡Q]T(y6 adjustments.
  2550.     °dONLNdŒitÄ*HPROCEDURE TextBoundingBox(s: Str255; numer,denom: Point; VAR box: Rect);°dONLNd}à@*   CONST°dONLNd áíS*
  2551. ?      FMgrOutRec = $998; { FMOutRec starts here in low memory }°dONLNd`ëúÅ*
  2552.       tabFont = 1024;°dONLNdvõ¶Ä*
  2553. H      { global width table offset for font record handle, see IM IV-41 }°dONLNdøØ∫;*   TYPE°dONLNd«πƒ§*
  2554.       FontRecPtr = ^FontRec;°dONLNd‰Õÿ6*   VAR°dONLNdÎ◊‚ü*
  2555.       hScale,vScale: Fixed;°dONLNd·Ï€*
  2556. '      err,intWidth,kernAdjust: Integer;°dONLNd/Έh*
  2557.       xy: Point;°dONLNd@ıl*
  2558. D      info: FontInfo;  { only for StdTxMeas; we'll use FontMetrics }°dONLNdÖˇ
  2559. &*
  2560. 6      fm: FMetricRec;  { see Inside Macintosh, IV-32 }°dONLNdº    Ü*
  2561.       fmOut: FMOutput;°dONLNd”h*
  2562.       h: Handle;°dONLNd‰'2@*   BEGIN°dONLNdÌ1<N*
  2563. >      intWidth := StdTxMeas(ord(s[0]),@s[1],numer,denom,info);°dONLNd    ,;FÔ*
  2564. +      { calls FMSwapFont and everything - }°dONLNd    XEPä*
  2565. J      { StdTxMeas returns possibly modified scaling factors numer, denom }°dONLNd    £OZÍ*
  2566. *      hScale := FixRatio(numer.h,denom.h);°dONLNd    œYdÍ*
  2567. *      vScale := FixRatio(numer.v,denom.v);°dONLNd    ˙cn5*
  2568. 9      { These are the scaling factors QuickDraw uses    }°dONLNd
  2569. 4mx5*
  2570. 9      { in "stretching" the available character bitmaps }°dONLNd
  2571. nwÇ—*
  2572. %      fmOut := FMOutPtr(FMgrOutRec)^;°dONLNd
  2573. îÅå5*
  2574. 9      { has been filled by the most recent FMSwapFont,  }°dONLNd
  2575. ŒãñÂ*
  2576. )      { implicitly called by StdTxMeas  }°dONLNd
  2577. ¯ï†:*
  2578. :      SetRect(box,0, - info.ascent,intWidth,info.descent);°dONLNd 3ü™˛*
  2579. .      { bounding box for unscaled plain text } ◊4◊˘
  2580. *&10)
  2581.  of 12(Ï∑
  2582. Fond of FONDsˇP◊#ˇ ˇˇˇˇ#◊ 
  2583. IR,Times
  2584. .+Z-Developer Support Center(-ÛMay 1992 /X/,
  2585. Courier
  2586.     °dONLNd<(ü(DZG      IF (italic IN thePort^.txFace) AND (fmOut.italic <> 0) THEN BEGIN°dONLNdH'<2ˇ*
  2587. '      { the following is heuristics … }°dONLNdp1<<ê*
  2588. D         box.right := box.right + (info.ascent + info.descent - 1) *°dONLNdµ;<F*
  2589. *                      fmOut.italic DIV 16;°dONLNd‡E<Pπ*
  2590.          FontMetrics(fm);°dONLNd˙O<Zê*
  2591. D         HLock(fm.WTabHandle); { We'll point to global WidthTable. }°dONLNd?Y<dw*
  2592. ?         h := Handle(LongPtr(ord4(fm.WTabHandle^) + tabFont)^);°dONLNdc<n^*
  2593. :         { Be sure it's a handle to a 'NFNT' or 'FONT' ! }°dONLNd∫m<x'*
  2594. /         kernAdjust := FontRecPtr(h^)^.kernMax;°dONLNdÍw<Ç    *
  2595. )         OffsetRect(box, - kernAdjust,0);°dONLNdÅ<å‹*
  2596.           HUnlock(fm.WTabHandle);°dONLNd5ã<ñn*
  2597.  
  2598.       END;°dONLNd@ï<†m*
  2599. =      IF (bold IN thePort^.txFace) AND (fmOut.bold <> 0) THEN°dONLNd~ü<™c*
  2600. ;         box.right := box.right + fmOut.bold - fmOut.extra;°dONLNd∫©<¥ê*
  2601. D      IF (outline IN thePort^.txFace) THEN InsetRect(box, - 1, - 1);°dONLNdˇ≥<æü*
  2602. G      IF (shadow IN thePort^.txFace) AND (fmOut.shadow <> 0) THEN BEGIN°dONLNdGΩ<»@*
  2603. 4         IF fmOut.shadow > 3 THEN fmOut.shadow := 3;°dONLNd|«<“'*
  2604. /         box.right := box.right + fmOut.shadow;°dONLNd¨—<‹1*
  2605. 1         box.bottom := box.bottom + fmOut.shadow;°dONLNdfi€<ÊÊ*
  2606. "         InsetRect(box, - 1, - 1);°dONLNdÂ<n*
  2607.  
  2608.       END;°dONLNd Ô<˙Å*
  2609. A      { Now scale the box (more or less) as QuickDraw would do. }°dONLNdN˘<©*
  2610. I      { Note that some of the adjustments are based on trial and error… }°dONLNdò<h*
  2611. <      box.top := FixRound(FixMul(Long2Fix(box.top),vScale));°dONLNd’
  2612. <Ü*
  2613. B      box.left := FixRound(FixMul(Long2Fix(box.left),hScale)) - 1;°dONLNd<"ö*
  2614. F      box.bottom := FixRound(FixMul(Long2Fix(box.bottom),vScale)) + 1;°dONLNd_!<,ê*
  2615. D      box.right := FixRound(FixMul(Long2Fix(box.right),hScale)) + 1;°dONLNd§+<6ë*
  2616.       GetPen(xy);°dONLNd∂5<@‹*
  2617.        OffsetRect(box,xy.h,xy.v);°dONLNd◊?<J_*
  2618.    END;
  2619. °dONLNdfla<pÖ*&
  2620. Conclusion
  2621. °dONLNdÍ|<à‡*#At the time when the original Font °dONLNd
  2622. |‡à˛)§7Manager architecture was designed, based on QuickDraw’s°dONLNdEà<îu(∞Z hard-coded °dONLNdPàuî˛)9O72 dpi resolution, nobody could anticipate that some years later, the Macintosh°dONLNd†î<†˝(ºZ%would be used to tackle professional °dONLNd≈˛)¡2typesetting projects. Several advanced page layout°dONLNd¯†<¨h(»Z@applications managed to work around the “built-in” limitations, °dONLNd8†h¨˛(»Üat high development costs, and°dONLNdW¨<∏Ø(‘ZBsome compatibility and performance problems. In many other cases, °dONLNdô¨Ø∏˛(‘Õhowever, those°dONLNd®∏<ƒì(‡Zlimitations caused °dONLNdª∏ìƒ˛)WFquestions to DTS and unsatisfying compromises. This Note can’t do much°dONLNdƒ<–Ω(ÏZOmore than explain the state of affairs; the real solution to the problems must °dONLNdQƒΩ–˛(Ï€ come from a°dONLNd]–<‹¯(¯Z&redesigned foundation. TrueType leads °dONLNdÉ–¯‹˛)º6the way and already fulfills many of the requirements;°dONLNd∫‹<Ë(Z-everything else is getting closer and closer.°dONLNdË< ¶*$Further Reference: +X+°dONLNd˚
  2623. NR+
  2624. •°dONLNd˝
  2625. `±)Inside Macintosh°dONLNd    
  2626. 
  2627. ±w)Q', Volume I, Chapter 7, The Font Manager°dONLNd    5N%R(Al•°dONLNd    7`%±)Inside Macintosh°dONLNd    G±%)Q(, Volume IV, Chapter 5, The Font Manager°dONLNd    p%N1R(Ml•°dONLNd    r%`1±)Inside Macintosh°dONLNd    Ç%±1{)Q', Volume V, Chapter 9, The Font Manager°dONLNd    ™1N=R(Yl•°dONLNd    ¨1`=±)Inside Macintosh°dONLNd    º1±=Ö)Q), Volume VI, Chapter 12, The Font Manager°dONLNd    Ê=NIR(el•°dONLNd    Ë=`I)New & Improved Inside Macintosh°dONLNd
  2628. =Iö)®, Imaging: The Font Manager. °dONLNd
  2629. $=öIÕ)í
  2630. Developer °dONLNd
  2631. .=ÕI˛)3    CD Series°dONLNd
  2632. 8I`UΔ(q~Jdisc, path Developer Essentials: Technical Docs: Inside Macintosh Previewf°dONLNd
  2633. ÉUNaR(}l•°dONLNd
  2634. ÖU`aú)<Macintosh Technical Note #91, Picture Comments—The Real Deal°dONLNd
  2635. ¬aNmR(âl•°dONLNd
  2636. ƒa`m∫)M.IM. FontNames°dONLNd
  2637. ‘mNyR(ïl•°dONLNd
  2638. ÷m`y–)M.TE.FontsAndScripts°dONLNd
  2639. ÎyNÖR(°l•°dONLNd
  2640. Ìy`Öæ)M.IM.FontFamilies°dONLNd
  2641. ˇÖNëR(≠l•°dONLNd Ö`ëÅ)Apple °dONLNd ÖÅë¯)!LaserWriter Reference, °dONLNd Ö¯ë˛)w/Chapter 2, Working With Fonts ( Addison-Wesley,°dONLNd Në`ù|(π~1988) ◊X◊
  2642. (ÏZ
  2643. Fond of FONDs(Ï˙11)
  2644.  of 12ˇˆ◊#ˇ ˇˇˇˇ#◊ 
  2645. IR,Times
  2646. .+6-Macintosh Technical Notes /4/˘
  2647. °dONLNd*+.+•°dONLNd<+L)1Adobe Technical Note #0091 (PostScript Developer °dONLNd3L+⁄(GjSupport Group), Macintosh°dONLNdM+<7ê(SZFOND Resources°dONLNd\COï(k6MPostScript and Adobe are registered trademarks of Adobe Systems Incorporated.°dONLNd™O[∂* XHelvetica and Palatino are registered trademarks of Linotype AG and/or its subsidiaries.°dONLNdgsJ* Velocio is °dONLNdgJs\)2not°dONLNdg\sŸ) a trademark of the author. ◊4◊˘
  2648. (Ï612)
  2649.  of 12(Ï∑
  2650. Fond of FONDsˇj◊#ˇ ˇˇˇˇ#◊†Ç 
  2651. /ZÅ#
  2652.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  2653. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  2654. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  2655. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  2656. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  2657.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  2658. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  2659. IR.°dONLNdn<ÅÁ(õZFont Manager Q&As
  2660. °dONLNdÄ<èZ*Text°dONLNdÄkè˛(´âM.TX.FontMgr.Q&As
  2661. °dONLNd*õ<ßt(√Z Revised by:°dONLNd6õÑߡ)HDeveloper Support Center°dONLNdOõæß˛(√‹ October 1992°dONLNd\ß<≥q(œZ Written by:°dONLNdhßÑ≥ˇ)HDeveloper Support Center°dONLNdÅßæ≥˛(œ‹ October 1990°dONLNdéø<À⁄(ÁZThis Technical Note contains a °dONLNd≠ø⁄À˛)û9collection of Q&As relating to a specific topic—questions°dONLNdÁÀ<◊†(ÛZGyou’ve sent the Developer Support Center (DSC) along with answers from °dONLNd.À†◊˛(Ûæthe DSC engineers.°dONLNdA◊<„u(ˇZ
  2662. While DSC °dONLNdK◊u„˛)9Lengineers have checked the Q&A content for accuracy, the Q&A Technical Notes°dONLNdò„<Ôq( Z don’t have °dONLNd£„qÔ˛)5Qthe editing and organization of other Technical Notes. The Q&A function is to get°dONLNdıÔ<˚Ÿ(Znew technical information and °dONLNdÔŸ˚˛)ù6updates to you quickly, saving the polish for when the°dONLNdJ˚<(#Z,information migrates into reference manuals.°dONLNdw<k*:Q&As are now included with Technical Notes to make access °dONLNd±k˛(;âto technical updates easier for°dONLNd—<+.(GZ/you. If you have comments or suggestions about °dONLNd.+˛)Ú*Q&A content or distribution, please let us°dONLNd++<7\(SZknow °dONLNd0+\7˛) Iby sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical°dONLNdz7<Ci(_Z9questions about Q&A content to DEVSUPPORT for resolution.°dONLNd¥O<[«*NNew Q&As and Q&As revised this month are marked with a bar in the side margin."n  ÜXÜ
  2663. °dONLNdÄ<è†*43Chicago Control-Q prints propeller or clover symbol
  2664. °dONLNd7è<õb* Written:°dONLNd@èàõ¶)L7/4/90°dONLNdGõ<ßÅ(√ZLast reviewed:°dONLNdVõàß¶)L8/1/92°dONLNd]≥<øp(€Z    How do I °dONLNdf≥pø˛)4Pget the character that represents the clover used for command-key equivalents in°dONLNd∑ø<À∂(ÁZdocuments and in menus?°dONLNdœÀ<◊N* ___°dONLNd”„<Ôç*DThis key is documented in the Apple Style Guide, which is available °dONLNd„çÔ˛( ´on the latest Developer°dONLNd/Ô<˚º(ZCD Series disc as well as °dONLNdIÔº˚˛)Ä=from APDA. One little feature of Key Caps which is not widely°dONLNdá˚<ß(#Zknown is the Control °dONLNdú˚߲)kAkey (not the Command or Option keys). Pressing the Control key in°dONLNdfi<>(/Z4Chicago shows that Control-Q in Chicago maps to the °dONLNd>˛(/\&propeller symbol for which you search.°dONLNd9<p(;Z
  2665. Control-Q °dONLNdCp·)4Kgenerates the character code 17; the standard Macintosh character set (see °dONLNdé·˛(;ˇInside°dONLNdï<+m(GZ    Macintosh°dONLNdûm+b)14 Volume VI, page 12-5) specifies this symbol for it. ◊X◊
  2666. (ÏZFont Manager Q&As(Ï1) of 8ˇ°¿Ù%%DSIDICT:_cv
  2667. currentdict /bu known {bu}if
  2668. userdict /_cv known not{userdict /_cv 30 dict put}if
  2669. _cv begin
  2670. /bdf{bind def}bind def
  2671. currentscreen/cs exch def/ca exch def/cf exch def
  2672. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  2673. /ss{//cf //ca //cs setscreen}bdf
  2674. /stg{ss setgray}bdf
  2675. /strgb{ss setrgbcolor}bdf
  2676. /stcmyk{ss cvcmyk}bdf
  2677. /min1{dup 0 eq{pop 1}if}bdf
  2678. end
  2679. currentdict /bn known {bn}if
  2680. †ø¶◊#ˇ ˇˇˇˇ#◊ 
  2681. IR,Times
  2682. .+6-Macintosh Technical Notes /4/˘
  2683. °dONLNd)8"*'&Determining Macintosh system font size
  2684. °dONLNd'8D>* Written:°dONLNd08dDà)L2/11/91°dONLNd8DP](l6Last reviewed:°dONLNdGDdPÇ)L8/1/92°dONLNdN\h5(Ñ6:How does a program determine the default system font size?°dONLNdâht** ___°dONLNdçÄåÏ*'If you want to know the default system °dONLNd¥ÄÏå⁄)‘.font size, use the GetDefFontSize call (Inside°dONLNd„åò—(¥6$Macintosh Volume V, page 314). This °dONLNdå—ò⁄)π:call will return the true default system font size. On all°dONLNdBò§C(¿6:Roman systems the sysFontSize low-memory global is always °dONLNd|òC§⁄(¿a zero by default; this means that°dONLNdù§∞_(Ã6Hit’s actually 12. Don’t ask me why they did this, but it’s true, so you °dONLNd§_∞⁄(Ã}should use the call if you°dONLNd∞º“(ÿ6_want a painless method of obtaining this information. Try to avoid reading the global directly.
  2685. °dONLNd`‘„M*',FScaleDisable and Macintosh screen rendering
  2686. °dONLNdç„Ô>* Written:°dONLNdñ„dÔÇ)L6/4/91°dONLNdùÔ˚](6Last reviewed:°dONLNd¨Ôd˚Ç)L8/1/92°dONLNd≥‹(/6+What is the current interface guideline on °dONLNdfi‹⁄)ƒ4font scaling? Should we set FScaleDisable to true or°dONLNdc(;6false for screen °dONLNd$c⁄)KQrendering? I believe the old guideline was to set it to true (thus disabling font°dONLNdv+ï(G6Sscaling) so that if you have a 23 pt screen font you will see 12 pt glyphs with 23 °dONLNd…ï+⁄(G≥
  2687. pt widths. We°dONLNd◊+7&(S62want performance on Apple’s low-end machines, and °dONLNd    +&7⁄(SD!we don’t want to make this a user°dONLNd+7CM(_6 preference.°dONLNd7CO** ___°dONLNd;[gâ*Most applications now °dONLNdQ[âg⁄)qEset FScaleDisable to false all the time. If you are worried about the°dONLNdógsï(è6speed degradation in your °dONLNd±gïs⁄)}?application when running on slower Macintosh systems, you could°dONLNdÒsΩ(õ6"have your software identify which °dONLNdsΩ⁄)•:Mac it is running on using Gestalt, SysEnvirons, etc., and°dONLNdNã≥(ß6Tthen set FScaleDisable to true only on the slow machines. From the purely interface °dONLNd¢≥ã⁄(ß—point of°dONLNd´ãó|(≥6Kview, “what-you-see-is-what-you-get” is best, if processor speed allows it.°dONLNd˜£غ*!With TrueType there is no issue, °dONLNd£ºØ⁄)§9since FScaleDisable doesn’t have any effect on an outline°dONLNdRت/(◊6font.
  2688. °dONLNdZ”‚1*'(Macintosh double-byte character encoding
  2689. °dONLNdÉ‚Ó>* Written:°dONLNdå‚dÓÇ)L8/5/91°dONLNdìÓ˙](6Last reviewed:°dONLNd¢Ód˙Ç)L8/1/92°dONLNd©7(.6When °dONLNdÆ7⁄)Uwill System 7 and TrueType be able to support a larger character encoding vector than°dONLNd:(:6=the current 256 characters? Is this something I could do now?°dONLNdB*** ___°dONLNdF6Bd*CSystem 7 does not have double-byte character encoding support now. °dONLNdâ6dB⁄(^ÇIn the future, Apple will°dONLNd£BN°(j6use the two-byte UNICODE °dONLNdºB°N⁄)â?standard for its operating systems. However, such a change will°dONLNd¸NZ6(v6?be huge and therefore will not be available in the near future.°dONLNd<frß*Ever since 6.0.2, KanjiTalk °dONLNdXfßr⁄)è9has had double-byte encoding, so you can use the Japanese°dONLNdír~(ö64system at this time. The system which allows you to °dONLNdΔr~⁄)˙+do this is called shift-JIS (Japanese Input°dONLNdÚ~äÅ(¶6JSystem). The mappings are on the current Developer CD in the Kanji folder. ◊4◊˘
  2690. *F2) of 8(Ï£Font Manager Q&Asˇ
  2691. ◊#ˇ ˇˇˇˇ#◊ 
  2692. IR,Times
  2693. .+Z-Developer Support Center(-Ê October 1992 /X/
  2694. °dONLNd<,_(HZ*'FOND' resource features subject to change
  2695. °dONLNd+,<8b* Written:°dONLNd4,à8¨)L6/17/91°dONLNd<8<DÅ(`ZLast reviewed:°dONLNdK8àD¶)L8/1/92°dONLNdRP<\¢(xZJWhich 'FOND' features are subject to change, and what parts can I rely on?°dONLNdù\<hN* ___°dONLNd°t<ÄA*4'FOND' features not documented in Inside Macintosh, °dONLNd’tAIJ(ú_%Macintosh Technical Notes, or develop°dONLNd˚Ä<å(®Z0are subject to change. That’s the official word.
  2696. °dONLNd,§<≥**'$Five font style-mapping table styles
  2697. °dONLNdQ≥<øb* Written:°dONLNdZ≥àø¨)L6/17/91°dONLNdbø<ÀÅ(ÁZLast reviewed:°dONLNdqøàÀ¶)L8/1/92°dONLNdx◊<„i(ˇZ?Why is “47” the bounds of the indexes’ array in the StyleTable?°dONLNd∏„<ÔN* ___°dONLNdº˚<ù*HThe style-mapping tables, which are used for mapping of a font style to °dONLNd˚ù˛(#ªa particular font for°dONLNd<{(/ZGprinting, have only five possible styles, unlike the six screen styles °dONLNda{˛(/ô(underline is omitted, since°dONLNd~<é(;ZIa laser printer just explicitly draws a line under the string—it doesn’t °dONLNd«é˛(;¨need a special font for°dONLNdfl<+Ë(GZPthat). You can have any combination of these five styles, EXCEPT that you can’t °dONLNd/Ë+˛(Ghave°dONLNd4+<7Ù(SZW“Condense” and “Extend” at the same time (Condensed Extended wouldn’t make a whole lot °dONLNdã+Ù7˛(Sof°dONLNdé7<C(_Z)sense). Thus you get (combinatorics come °dONLNd∑7C˛)À2back to haunt us) 48 possible unique styles to map°dONLNdÍC<OI(kZto.°dONLNdÓ[<g]*X-Ref:°dONLNdıg<s* 'Snippet “StyleMap” on the Developer CD.°dONLNds<Œ* NLaserWriter Reference, Chapter 2, “Working with Fonts,” (Addison-Wesley; APDA °dONLNdksŒ˛(õÏ #M7073,°dONLNdt<ãf(ßZ$19.95).
  2698. °dONLNd}£<≤˘*'System 7 and modified fonts
  2699. °dONLNdô≤<æb* Written:°dONLNd¢≤àæ¨)L6/21/91°dONLNd™æ< Å(ÊZLast reviewed:°dONLNdπæà ¶)L8/1/92°dONLNd¿÷<‚Ó(˛Z!We ship modified versions of the °dONLNd·÷Ó‚˛)≤/Chicago and Geneva fonts and their FONDs in our°dONLNd‚<Ó(
  2700. Z)application’s resource fork. With System °dONLNd:‚Ó˛) /6, when we ask for font 0 or font 3, we get our°dONLNdjÓ<˙·(ZWmodified fonts in windows, buttons, menus and dialogs, but not with System 7. Is there °dONLNd¡Ó·˙˛(ˇa new°dONLNd«˙<‹("ZYway to tell System 7 to use my version of Chicago 12 to display all system related stuff?°dONLNd!<N* ___°dONLNd%<*q*?What’s happened is that the system software is being much more °dONLNddq*˛(Fèstrict about whose “Chicago”°dONLNdÅ*<6n(RZ it uses for °dONLNdç*n6˛)2Lmenus and dialogs. The Menu and Control Managers now only look at the system°dONLNd⁄6<B≈(^Zfile for the Chicago they use.°dONLNd˘N<Z„*"There are a couple of ways to get °dONLNdN„Z˛)ß9around this: First, you can try patching DrawString right°dONLNdUZ<fº(ÇZbefore calling MenuSelect °dONLNdoZºf˛)Ä=in your program. The patch would select your Chicago and then°dONLNd≠f<r˛(éZ'jump to the standard DrawString. After °dONLNd‘f˛r˛)¬1MenuSelect, remove the patch. The disadvantage of°dONLNdr<~±(öZthis method is that, if a °dONLNd r±~˛)uAfuture system software release doesn’t use DrawString for drawing°dONLNdb~<ä#(¶Z0menus, the patch would cease to have any effect. ◊X◊
  2701. *FFont Manager Q&As(Ï3) of 8ˇú◊#ˇ ˇˇˇˇ#◊ 
  2702. IR,Times
  2703. .+6-Macintosh Technical Notes /4/˘
  2704. °dONLNd)˝*0A better solution is to write your own menu and °dONLNd0˝)⁄)Â,control definition code—in other words, your°dONLNd])5\(Q6?own custom MDEF and CDEFs. The way you typically do this is to °dONLNdú)\5⁄(Qzget a copy of the standard°dONLNd∑5A{(]6Macintosh system’s °dONLNd 5{A⁄)cEMDEF or CDEF, and alter it to your specifications. In your case, this°dONLNdAMÀ(i6$would be merely selecting your font °dONLNd4AÀM⁄)≥4instead of the system font. Name your font something°dONLNdiMYU(u6Dother than Chicago and just select that font by name in the menu or °dONLNd≠MUY⁄(uscontrol’s draw routine. The°dONLNd…Yeq(Å6Control and Menu °dONLNd⁄Yqe⁄)YFManager chapters in Inside Macintosh Volume I have more information on°dONLNd!eq_(ç6Fwriting custom definitions. There is only one problem with this right °dONLNdge_q⁄(ç}now: While the System 6°dONLNdq}s(ô6MDEF and CDEF °dONLNdçqs}⁄)[Hare available on AppleLink, the System 7 versions are not available yet,°dONLNd÷}âô(•6although they will be soon.°dONLNdÚï°©*RA note on the use of Chicago in your application: As the June 1991 edition of the °dONLNdDï©°⁄(Ω«    Macintosh°dONLNdN°≠%(…65Technical Note “Font Family Numbers” mentions, fonts °dONLNdɰ%≠⁄(…C$are copyrighted material. Apple owns°dONLNd®≠π«(’6%the Chicago font and typeface, so be °dONLNdÕ≠«π⁄)Ø9sure you check into licensing issues before releasing any°dONLNdπ≈ (·65version, altered or unaltered, with your application.
  2705. °dONLNd=›Ïˇ*' Spanish typographic measurements
  2706. °dONLNd^ϯ>* Written:°dONLNdgÏd¯é)L12/10/91°dONLNdp¯]( 6Last reviewed:°dONLNd¯dÇ)L8/1/92°dONLNd܇(86&What typographical measurement issues °dONLNd¨‡⁄)».must be considered for Spanish systems? Do the°dONLNd€(4(D6=Spanish specify type in ciceros and didots instead of points?°dONLNd(4** ___°dONLNd@L¨*SIf typesetting is done in Spain with computers, U.S. standards generally are used. °dONLNdp@¨L⁄(h 
  2707. It is only°dONLNd{LX≥(t6Vwhen typesetting is done the old-fashioned way that you’ll see different measurements.°dONLNd“dp"*8Paper sizes are different. In Spain DIN-44 (210 x 297), °dONLNd
  2708. d"p⁄(å@#DIN-A3 (420 x 297) and “folio” (215°dONLNd.p|!(ò6x °dONLNd0p!|⁄)    X315) are used. As always, you’ll be working with 72 dpi for the screen (and any time you°dONLNdâ|àŸ(§6'use QuickDraw) but something different °dONLNd∞|Ÿà⁄)¡3on paper, so you’ll need to use PrGeneral and image°dONLNd‰àîå(∞6Qthe stuff yourself to a resolution that allows you control over your imaging for °dONLNd5àåî⁄(∞™printing. This is°dONLNdGî†˚(º6.detailed in the article, “Meet PrGeneral, the °dONLNduî˚†⁄)„(Trap That Makes the Most of the Printing°dONLNdû†¨π(»6!Manager,” in issue #3 of develop.°dONLNd¿∏ƒ›*(Here are the measurements used in Spain:°dONLNdÈ–‹«*#• Decimal point (Didot) (0.3759 mm)°dONLNd
  2709. ‹ËO* • Millimeter°dONLNdËÙú* • Cicero (12 decimal points)°dONLNd7ÙR* • Centimeter°dONLNdD >* • Inches ◊4◊˘
  2710. *ƒ4) of 8(Ï£Font Manager Q&AsˇT◊#ˇ ˇˇˇˇ#◊ 
  2711. IR,Times
  2712. .+Z-Developer Support Center(-Ê October 1992 /X/
  2713. °dONLNd)<83(TZ"SetOutlinePreferred = TRUE or not?
  2714. °dONLNd#8<Db* Written:°dONLNd,8àD¨)L12/2/91°dONLNd4D<PÅ(lZLast reviewed:°dONLNdCDàP¶)L8/1/92°dONLNdJ\<hÌ(ÑZUMy application calls SetOutlinePreferred so outline fonts are used if both bitmapped °dONLNdü\Ìh˛(Ñ and°dONLNd£h<tn(êZ    TrueType °dONLNd¨hnt˛)2Pfonts are in the system. It was reported to me, however, that some international°dONLNd˝t<Ä€(úZ"TrueType fonts in particular look °dONLNdt€Ä˛)ü=really bad at small point sizes on the screen. Should I avoid°dONLNd]Ä<åû(®Zcalling this function?°dONLNdtå<òN* ___°dONLNdx§<∞„*XSetOutlinePreferred is best used as a user-selectable option. Along the same lines, you °dONLNd–§„∞˛(Ãmight°dONLNd÷∞<ºb(ÿZwant to °dONLNdfi∞bº˛)&Rinclude the SetPreserveGlyph call (Inside Macintosh Volume VI, page 12-21), again,°dONLNd1º<»ª(‰Zas a user-selectable option.°dONLNdN‘<‡Ó*$Currently, as you know, the default °dONLNdr‘Ó‡˛)≤8for outlinePreferred is FALSE; this is for compatibility°dONLNd´‡<Ϙ(Z&reasons (existing documents don’t get °dONLNd—‡˜Ï˛)ª6reflowed if the bitmap fonts are still around) and for°dONLNdÏ<¯Ê(ZYesthetic and performance reasons (users are free to maintain bitmap fonts in the smaller °dONLNdaÏʯ˛(point°dONLNdg¯<Ä( ZHsizes if the TrueType version is not satisfying for small sizes, or too °dONLNdدIJ( ûslow). On the other hand,°dONLNd…<|(,Z
  2715. as soon as a °dONLNd÷|˛)@Obitmap font is *un*available for a requested point size, and an outline font is°dONLNd&<”(8Z"present, the outline font is used °dONLNdH”˛)ó<even with outlinePreferred = FALSE. Setting outlinePreferred°dONLNdÖ<(T(DZ7= TRUE makes a difference only for point sizes where a °dONLNdºT(˛(Dr#bitmap font strike is present along°dONLNd‡(<4Ï(PZ'with a 'sfnt' in the same family/style.°dONLNd@<Lfi*[TrueType fonts might be preferable even for small point sizes if linearly scaled character °dONLNdc@fiL˛(h¸widths°dONLNdjL<Xõ(tZCare more important than screen rendering: If the main purpose of a °dONLNd≠LõX˛(tπprogram is preprint°dONLNd¡X<d÷(ÄZ!processing for a high-resolution °dONLNd‚X÷d˛)ö;output device, then outlinePreferred = TRUE may give better°dONLNdd<pQ(åZline °dONLNd#dQp˛)Xlayout results on the printer, at the price of “not so great” type rendering on a 72 dpi°dONLNd|p<|8(òZ6screen. (An example for the conflict between linearly °dONLNd≤p8|˛)¸(scaling TrueType and non-linearly scaled°dONLNd€|<àÖ(§Zbitmap fonts is °dONLNdÎ|Öà˛)IOHelvetica: StringWidth('Lilli') returns 19 for the 12-point bitmap font, and 15°dONLNd;à<îÒ(∞Z&for the 13-point  size from TrueType!)°dONLNdb†<¨e*    All this °dONLNdk†e¨˛))Oboils down to the recommendation stated initially: The user should be given the°dONLNdª¨<∏·(‘Z%flexibility to decide whether to use °dONLNd‡¨·∏˛)•:the existing bitmaps (using TrueType only for bigger point°dONLNd∏<ƒV(‡Zsizes °dONLNd!∏Vƒ˛)Yand high-resolution printers), or to go with TrueType even if the result on the screen is°dONLNd{ƒ<–N(ÏZnot °dONLNdƒN–˛)Zoptimal. (By the way, it’s likely that TrueType development will substantially reduce this°dONLNd⁄–<‹£(¯Zconflict in the future.)
  2716. °dONLNdÛÙ<¬*'7FontRec fontType field and determining monospaced fonts
  2717. °dONLNd    +<b* Written:°dONLNd    4à¨)L1/13/92°dONLNd    <<Å(7ZLast reviewed:°dONLNd    Kà¶)L8/1/92°dONLNd    R'<3
  2718. (OZ+How can I create a menu that contains only °dONLNd    }'
  2719. 3˛)Œ0fixed width fonts? The FontRec record’s fontType°dONLNd    Æ3<?z([Zfield doesn’t °dONLNd    º3z?˛)>Qcorrectly tell me if the font is fixed width as Inside Macintosh Volume V says it°dONLNd
  2720. ?<K‘(gZUshould. All system fonts appear to have the same fontType regardless of whether they °dONLNd
  2721. c?‘K˛(gÚ    are fixed°dONLNd
  2722. mK<W+(sZ6or proportional. Currently I test if the width of the °dONLNd
  2723. £K+W˛)Ô,characters “m” and “i” are equal and if they°dONLNd
  2724. –W<c©(ZQare, I consider the font to be fixed width. Is there an easier (and faster!) way?°dONLNd "c<oN* ___°dONLNd &{<áfi*The Font Manager documentation °dONLNd E{fiá˛)¢=is not explicit enough about the fact that bit 13 (0x2000) of°dONLNd Éá<ì2(ØZ6the fontType field is basically useless. Neither does °dONLNd πá2ì˛)ˆ*the Font Manager check the setting of this°dONLNd ‰ì<üœ(ªZMbit, nor does QuickDraw (or any printer driver). As you observed, monospaced °dONLNd 1ìœü˛(ªÌ
  2725. fonts like°dONLNd <ü<´¸(«Z%Monaco or Courier don’t have the bit °dONLNd aü¸´˛)¿4set; so the meaning of this bit is just perverted to ◊X◊
  2726. (ÏZFont Manager Q&As(Ï5) of 8ˇ¨◊#ˇ ˇˇˇˇ#◊ 
  2727. IR,Times
  2728. .+6-Macintosh Technical Notes /4/˘
  2729. °dONLNd)*0nonsense—sorry! In addition, the fontType field °dONLNd0)⁄)È*only is available for 'FONT's and 'NFNT's;°dONLNd[)5V(Q6Eit does not exist in 'sfnt's, and you would have to check separately °dONLNd†)V5⁄(Qtfor the resource type of the°dONLNdΩ5A/(]6font.°dONLNd√MYF*?Your idea of comparing the widths of “m” and “i” (or any other °dONLNdMFY⁄(udcharacters which are extremely°dONLNd!Ye(Å65unlikely to have the same widths in a proportionally °dONLNdVYe⁄)˜*spaced font) is indeed the only reasonable°dONLNdÅeqÈ(ç6,way of figuring out if a font is monospaced.
  2730. °dONLNdÆâòe*'3Getting global width table for a font specification
  2731. °dONLNd‚ò§>* Written:°dONLNdÎòd§à)L4/22/92°dONLNdÛ§∞](Ã6Last reviewed:°dONLNd§d∞Ç)L8/1/92°dONLNd    º»Ø(‰6What’s the fastest way to get °dONLNd'ºØ»⁄)ó:the width table for a given font? FontMetrics is too slow,°dONLNdb»‘U(6especially in °dONLNdp»U‘⁄)=Ucolor. Is there any other call that will get the global width table set up correctly?°dONLNdΔ‘‡(¸66That is all that we need from the call to FontMetrics.°dONLNd˝‡Ï** ___°dONLNd¯´*OFontMetrics does not have much overhead in setting up the width table. It does °dONLNdP¯´⁄( …a dummy°dONLNdX)(,6<DrawChar(' '); this is very rapidly transformed into a call °dONLNdî)⁄(,G#to StdText, and StdText immediately°dONLNd∏¯(86+calls StdTxMeas. The first thing StdTxMeas °dONLNd„¯⁄)‡,does is to set up the input parameters for a°dONLNd(§(D6FMSwapFont call and call it. °dONLNd-§(⁄)å=FMSwapFont is the heart of the Font Manager, and does all the°dONLNdk(4Ä(P6work. It comes back °dONLNd(Ä4⁄)hDwith the FMOutput record, the font strike, and the width table. From°dONLNdƒ4@2(\6=there, FontMetrics derives the values it needs to bring back.°dONLNdLX…* You probably wouldn’t save much °dONLNd"L…X⁄)±5more than 1/1000th of a second if, instead of calling°dONLNdXXdΔ(Ä6WFontMetrics, you called FMSwapFont explicitly yourself—our only alternative suggestion.°dONLNd∞p|*-The Font Manager does quite a lot of caching °dONLNd›p|⁄)ÿ/(up to 12 width tables), and managing the cache°dONLNd
  2732. |à3(§6takes °dONLNd|3à⁄)Ysome cycles, too. If there is nothing in the cache corresponding to the font request, the°dONLNdmàîJ(∞6@cache makes the call even slower than it would be without cache.°dONLNdƆ¨ƒ*#The next source of overhead is the °dONLNd—†ƒ¨⁄)¨6Resource Manager. Looking for a specific font involves°dONLNd¨∏ (‘65going through the whole resource chain first for the °dONLNd=¨ ∏⁄(‘>"FOND (if none is found, the search°dONLNd`∏ƒ´(‡6Rrestarts for a FONT), and then, based on the FOND’s font association table, for a °dONLNd≤∏´ƒ⁄(‡…NFNT or°dONLNd∫ƒ–√(Ï6!'sfnt'. If no NFNT is found, the °dONLNd€ƒ√–⁄)´4search restarts for a FONT, always through the whole°dONLNd–‹É(¯6resource chain. For a °dONLNd&–É‹⁄)kDhuge resource fork like in the System file (and, maybe, also in your°dONLNdk‹ËΩ(6$application), the time spent in the °dONLNdè‹ΩË⁄)•8Resource Manager is not negligable—in particular, if you°dONLNd»ËÙ¡(6Whave add-ons in your system (such as INITs or 'cdev's) that patch out Resource Manager °dONLNd    Ë¡Ù⁄(flcalls,°dONLNd    &Ù8(6;maybe several times, and usually slow it down considerably!°dONLNd    b ¥*REven in case this hurdle is overcome swiftly (after all, the Resource Manager has °dONLNd    ¥ ¥⁄(4“its own°dONLNd    º$„(@6+caching scheme for optimization), the next °dONLNd    Á„$⁄)À2step necessarily takes some time, and, as you have°dONLNd
  2733. $0;(L6@observed, especially on a color system: It consists of actually °dONLNd
  2734. Z$;0⁄(LY!providing the bitmap for the font°dONLNd
  2735. |0<U(X6strike. If the °dONLNd
  2736. ã0U<⁄)=Sscreen depth is >1, this involves creating “synthetic” fonts for the correct screen°dONLNd
  2737. fl<HÑ(d6depth, to optimize text °dONLNd
  2738. ˜<ÑH⁄)lKdrawing. Also, if the font is an outline font, the first time a font strike°dONLNd CHT:(p6@has to be rasterized is quite costly in terms of machine cycles.°dONLNd Ñ`lµ* Finally, the width table can be °dONLNd §`µl⁄)ù;created; and, because of the scaling factors involved, this°dONLNd ‡lxÄ(î6Jrequires 256 times some arithmetic which is known never to be fast enough.°dONLNd +Ñê*5All this certainly gives us an understanding for the °dONLNd `Ñê⁄))time it takes FMSwapFont (FontMetrics) to°dONLNd äêú(∏65get the job done, but it does not solve your problem. ◊4◊˘
  2739. *46) of 8(Ï£Font Manager Q&Asˇº◊#ˇ ˇˇˇˇ#◊ 
  2740. IR,Times
  2741. .+Z-Developer Support Center(-Ê October 1992 /X/
  2742. °dONLNd<)ô(EZDepending on how °dONLNdô)˛)]Kpredictable the usage of fonts and width tables in your application is, you°dONLNd])<5«(QZmight consider building kind °dONLNdz)«5˛)ã?of a database of width tables beforehand, or along the way, and°dONLNd∫5<AŸ(]ZXuse this information directly from within your application. There is no shortcut at all °dONLNd5ŸA˛(]˜through°dONLNdA<MÑ(iZ
  2743. the Resource °dONLNd'AÑM˛)HEManager to get at the font resources, and there is no shortcut within°dONLNdmM<YÊ(uZ"FMSwapFont, like not building the °dONLNdèMÊY˛)™8font bitmaps. (To the best of my knowledge, the needbits°dONLNd»Y<e–(ÅZRfield in the FMInput record does *not* have this effect.) The only obvious way to °dONLNdY–e˛(ÅÓ    get width°dONLNd$e<q†(çZMtables faster is to keep them around, and to extend manually the capacity of °dONLNdqe†q˛(çæthe Font Manager’s°dONLNdÑq<}£(ôZcache of width tables.
  2744. °dONLNdõï<§l*'-SetFractEnable and recalculating width tables
  2745. °dONLNd…§<∞b* Written:°dONLNd“§à∞¶)L5/5/92°dONLNdŸ∞<ºÅ(ÿZLast reviewed:°dONLNdË∞ຶ)L8/1/92°dONLNdÔ»<‘m(Z=Calling SetFractEnable seems to force the width tables to be °dONLNd,»m‘˛(ãrecalculated regardless of the°dONLNdK‘<‡ (¸ZVsetting of the low-memory global FractEnable. We’re calling this routine at a central °dONLNd°‘ ‡˛(¸Ë entry point°dONLNd≠‡<Ïo(Z<for any document, as it’s a document by document attribute. °dONLNdȇoÏ˛(çWe then unconditionally call°dONLNdÏ<¯p(ZASetFractEnable(false) on exit back to the event loop, to be nice °dONLNdGÏp¯˛(éto other applications. Calling°dONLNdf¯<Ã( ZSetFractEnable(false), seems °dONLNdɯÃ˛)ê>to trigger the recalculation even though FractEnable is false.°dONLNd¬<ˆ(,Z'What’s the best way to get around this?°dONLNdÍ<N* ___°dONLNdÓ(<4W*Your °dONLNdÛ(W4˛)Yobservation is correct. The SetFractEnable call stuffs the boolean parameter (as a single°dONLNdM4<@](\Z;byte) into the low-memory global $BF4 and indiscriminately °dONLNdà4]@˛(\{"invalidates the cached width table°dONLNd´@<L∏(hZJby setting $B4C (LastSpExtra) to -1 (LongWord = Fixed). Obviously, it was °dONLNdı@∏L˛(h÷not anticipated°dONLNdL<X˝(tZ*that SetFractEnable could be called quite °dONLNd/L˝X˛)¡5regularly with a parameter that often does not change°dONLNdeX<dÙ(ÄZ^the previous setting. (By the way, the same observation applies to the SetFScaleDisable call).°dONLNdƒp<|N*9In your case, you may want to replace the SetFractEnable °dONLNd˝pN|˛(òl$call by your own test of the boolean°dONLNd"|<àW(§Z<(8-bit) in $BF4 (FractEnable), and call SetFractEnable only °dONLNd^|Wà˛(§u$if the parameter passed is different°dONLNdÉà<îÜ(∞Zfrom the value °dONLNdíàÜî˛)JIstored in $BF4. Note that Inside Macintosh Volume IV (page 32) explicitly°dONLNd‹î<†°(ºZNallows you to hack the $BF4 location directly, so it’s unlikely there are any °dONLNd*î°†˛(ºøfuture compatibility°dONLNd?†<¨w(»Z problems if °dONLNdK†w¨˛);Kyou go your own way around the original SetFractEnable. The only additional°dONLNdó¨<∏º(‘ZHinformation you need is what’s mentioned above: The Font Manager always °dONLNdfl¨º∏˛(‘⁄ checks $B4C°dONLNdÎ∏<ƒ\(‡Z;(LastSpExtra) for -1 before doing anything with the global °dONLNd    &∏\ƒ˛(‡z!width table; if it finds ($B4C) =°dONLNd    Hƒ<–#(ÏZ3LongInt(-1), it painfully rebuilds the width table.°dONLNd    |‹<Ë≠*Another comment: You °dONLNd    ë‹≠˲)qFdo not need to think of other applications when resetting FractEnable;°dONLNd    ÿË<Ù…(Zin a context switch to another °dONLNd    ˜Ë…Ù˛)ç>application, all low-memory globals are swapped anyway. Still,°dONLNd
  2746. 6Ù<ò(ZFthe above optimization of SetFractEnable probably is useful even when °dONLNd
  2747. |Ùò˛(∂you don’t call it any°dONLNd
  2748. í< ((Z.more systematically on exit to the event loop.
  2749. °dONLNd
  2750. ¡$<3ã*'2Corrupted Macintosh font or font suitcase criteria"CW
  2751. °dONLNd
  2752. Ù3<?b* Written:°dONLNd
  2753. ˝3à?¨)L6/19/92"RW °dONLNd ?<KÅ(gZLast reviewed:°dONLNd ?àK¨)L9/15/92"^W "jW °dONLNd W<c(Z*I would like to be able to detect whether °dONLNd FWc˛)»2a font suitcase is corrupted when it is opened and"vW °dONLNd yc<o(ãZ[whether any of the fonts in it are corrupted before any of the fonts are used. I know that °dONLNd ‘co˛(ãthe"ÇW °dONLNd ÿo<{¬(óZTFinder is able to do this, and I was wondering if Apple gives out this information. °dONLNd ,o¬{˛(ó‡
  2754. My program"éW °dONLNd 7{<á¿(£Zwill only run under System °dONLNd R{¿á˛)Ñ@7.0 if that helps. Any information that you can give me would be"öW °dONLNd ìá<ìò(ØZgreatly appreciated."¶W °dONLNd ®ì<üN* ___"≤W "æW  ◊X◊
  2755. *1Font Manager Q&As(Ï7) of 8ˇ Ê◊#ˇ ˇˇˇˇ#◊ 
  2756. IR,Times
  2757. .+6-Macintosh Technical Notes /4/˘
  2758. °dONLNd)‹*)The Finder and the type architecture are °dONLNd)‹)⁄)ƒ5living things; the definition of what is and is not a"<3 °dONLNd_)5Ì(Q6,damaged suitcase can change from release to °dONLNdã)Ì5⁄)’/release of system software. However, any of the"H3 °dONLNdª5As(]6Gfollowing conditions makes System 7.0 report the suitcase as “damaged”:"T3 "`3 °dONLNdMY*0• More than eight FONDs reference the same font."l3 "x3 °dONLNd4eqÂ*,• A new stand-alone object can’t be created °dONLNd`eÂq⁄)Õ4for a font icon. The usual cause of this is that two"Ñ3 °dONLNdïq}Ö(ô6LFONDs have the same name for the first 31 characters, and the Finder thinks °dONLNd·qÖ}⁄(ô£there’s already an"ê3 °dONLNdÙ}âì(•6Nicon in that window with the same name. (Two icons in the same directory with °dONLNdB}ìâ⁄(•±
  2759. the same name"ú3 °dONLNdPâï{(±6is a sign of damage.)"®3 "¥3 °dONLNdf°≠à*• There must be at least °dONLNd°à≠⁄)pIone font association table entry, and the table can’t go past the logical"¿3 °dONLNd…≠πv(’6end of the resource."Ã3 "ÿ3 °dONLNdfi≈—ë*N• The first resource name in the map must not be zero-length (which is a test °dONLNd,≈ë—⁄(ÌØfor some older"‰3 °dONLNd;—›Ø(˘6!third-party corrupted suitcases)."3 "¸3 °dONLNd]ÈıØ*• The FOND must have a name."3 "3 °dONLNdz
  2760. q*• The FOND must °dONLNdäq
  2761. ⁄)YMhave a valid character range—the first character has to be less than the last" 3 °dONLNdÿ
  2762. H(56>character—unless it is a "dummy" FOND (created on the fly for °dONLNd
  2763. H⁄(5fold standalone FONTs; in this",3 °dONLNd4%ã(A6case, last character = 0)."83 "D3 °dONLNdO1=|*O• All the font association table entries must be in ascending point size order."P3 "\3 °dONLNdüIU¡*\• No two font association table entries may reference exactly the same point size and style."h3 "t3 °dONLNd¸am»*^• The offsets to the width table, kerning table and style mapping table must be valid or zero."Ä3 "å3 °dONLNd[yÖP*D• The font ID must not be zero unless it’s actually the system font."ò3 "§3 °dONLNd†ëùé*We can’t promise this °dONLNd∂ëéù⁄)v=is every reason the Finder would report a suitcase as damaged"∞3 °dONLNdÙù©0(≈6=(especially given the second step), but this is most of them."º3  ◊4◊˘
  2764. (Ï68) of 8(Ï£Font Manager Q&Asˇfi◊#ˇ ˇˇˇˇ#◊†Ç 
  2765. /ZÅ#
  2766.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  2767. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  2768. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  2769. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  2770. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  2771.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  2772. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  2773. IR.°dONLNdz<ç/(ßZFonts and the Script Manager
  2774. °dONLNdå<õZ*Text°dONLNd#åfõ˛(∑ÑM.TE.FontsAndScripts
  2775. °dONLNd8ß<≥q(œZ Written by:°dONLNdDßÑ≥
  2776. )HJohn Harvey & Peter Edberg°dONLNd_ßÕ≥˛(œΠ   June 1989°dONLNdiø<Àû(ÁZThis Technical Note °dONLNd}øûÀ˛)bGdescribes how the Script Manager uses the font family ID to determine a°dONLNd≈À<◊s(ÛZ script code. X°dONLNd“Ò<˝k*&
  2777. The traps ,
  2778. Courier°dONLNd‹k¸∏)/ _FontScript°dONLNdÁÒ∏˝ø)M, °dONLNdÈø¸ ) _IntlScript°dONLNdÙÒ ˝)M, °dONLNdˆÒ˝()and °dONLNd˙(¸|) _Font2Script°dONLNdÒ|˝˛)T all use a font family ID to°dONLNd#˝<    í(%ZHdetermine the script interface system code that they return.  This Note °dONLNdk˝í    ˛(%∞describes the process,°dONLNdÇ    <k(1Z:the way the Script Manager renumbers the Chicago font for °dONLNdº    k˛(1ânon-Roman systems, and the°dONLNd◊<!F(=Z9equation for calculating Script IDs from font family IDs.°dONLNd.<:W*On a °dONLNd.W:„)Roman system the Chicago °dONLNd/-„9
  2779. )å'FOND'°dONLNd5.
  2780. :˛)*/ is numbered zero, but this causes no confusion°dONLNde:<FÙ(bZ(since Chicago is also the system font.  °dONLNdç:ÙF˛)∏2Non-Roman systems must renumber Chicago so that it°dONLNd¿G<S˝(oZ'will not interfere with the mapping of °dONLNdÁF˝R^)¡
  2781. 'FOND' ID = 0°dONLNdÙG^S©)a to the correct °dONLNdG©S–)Ksystem °dONLNd F–R˙)''FOND'°dONLNdG˙S˛)*.°dONLNdS<_    ({Z)Typically Chicago is renumbered to 16383.°dONLNd>l<xI*In °dONLNdAlIxö)
  2782. Inside Macintosh°dONLNdQlöxü)Q5, Volume V-293, The Script Manager, the descriptions °dONLNdÜlüx≠(îΩof °dONLNdâk≠w˙) _FontScript°dONLNdîl˙x˛)M,°dONLNdñx<Ñâ(°Z _IntlScript°dONLNd°yâÖ¶)M, and °dONLNdßx¶Ñ˙) _Font2Script°dONLNd≥y˙Ö„)T3 state that the current font identification number °dONLNdÊy„Ö˛)È(e.g.,°dONLNdÌÖ<ëf(ÆZ'FOND'°dONLNdÛÜfím)*9 ID) is used to calculate the correct script code.   The °dONLNd,Ümí˛(Æãequation for calculating script°dONLNdLì<üt(ªZ codes from °dONLNdWítûû)8'FOND'°dONLNd]ìûüÙ)* IDs is as follows:
  2783.     °dONLNdq´∞∂n+&script =((FONDid - $4000) DIV 512) + 1
  2784. °dONLNdò¡<Õi(ÈZ9For a specific example, consider the Kyoto font which is °dONLNd—¡iÕ˛(Èáone of the fonts included in°dONLNdÓŒ<⁄á(ˆZKanjiTalk.  Its °dONLNd˛Õ៱)K'FOND'°dONLNdŒ±⁄*)* ID is 16385.  Plugging °dONLNdŒ*⁄˛)y+that value into the equation above, we get:°dONLNdH⁄<Êm(Z?script = ((16385-16384) DIV 512) +1.  Which results in a value °dONLNdá⁄mÊ˛(ãof one, the script code for the°dONLNdßÊ<Úõ(ZKanji script system.°dONLNdº˛<
  2785. ∏*Note that this means that °dONLNd÷˛∏
  2786. ˛)|?script systems other than Roman can only have 512 separate font°dONLNd
  2787. <g(2Z<families.  Furthermore, Roman font families (FOND) must not °dONLNdR
  2788. g˛(2Öhave an ID greater than 16383,°dONLNdq<#P(?Zand °dONLNduP"z)'FOND'°dONLNd{z#í)*7 ID 16383 is reserved for Chicago on non-Roman systems.
  2789. °dONLNd≥;<J›(fZSo How Do They Work?
  2790. °dONLNd»V<bâ* _FontScript°dONLNd”Wâcê)M, °dONLNd’Vêb›) _IntlScript°dONLNd‡W›c¯)M, and °dONLNdÊV¯bL) _Font2Script°dONLNdÚWLcl)T begin °dONLNd˘Wlc˛) by setting two Script Manager°dONLNdd<ph(åZ    globals, °dONLNd choí),Forced°dONLNd&dípØ)* and °dONLNd+cØo‡)Default°dONLNd2d‡pM)1 to false.  Then the °dONLNdGdMp–)mtwo special font family (°dONLNd`c–o˙)É'FOND'°dONLNdfd˙p˛)*)°dONLNdhp<|á(òZCnumbers zero and one are mapped to the System and Application font. ◊X◊
  2791. *TFonts and the Script Manager(Ï1) of 4ˇ°¿Ù%%DSIDICT:_cv
  2792. currentdict /bu known {bu}if
  2793. userdict /_cv known not{userdict /_cv 30 dict put}if
  2794. _cv begin
  2795. /bdf{bind def}bind def
  2796. currentscreen/cs exch def/ca exch def/cf exch def
  2797. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  2798. /ss{//cf //ca //cs setscreen}bdf
  2799. /stg{ss setgray}bdf
  2800. /strgb{ss setrgbcolor}bdf
  2801. /stcmyk{ss cvcmyk}bdf
  2802. /min1{dup 0 eq{pop 1}if}bdf
  2803. end
  2804. currentdict /bn known {bn}if
  2805. †øé◊#ˇ ˇˇˇˇ#◊ 
  2806. IR,Times
  2807. .+6-Macintosh Technical Notes /4/˘
  2808. °dONLNd*G*    Next the ,
  2809. Courier°dONLNd    G)q)/'FOND'°dONLNdq*v)* °dONLNdv*v)5ID is tested to see if it is an international font.  °dONLNdEv)√(Fî _FontScript°dONLNdP√*⁄)M and°dONLNdU*6e(S6 _IntlScript°dONLNd`+e7i)M °dONLNda+i7
  2810. )!simply take the value out of the °dONLNdÇ*
  2811. 67)§txFont°dONLNdà+77û)* field of the current °dONLNdû*û6÷)ggrafPort°dONLNd¶+÷7⁄)8.°dONLNd©7Cl(`6 _Font2Script°dONLNdµ8lDI)T2 uses the value passed to it.  The test is simply:
  2812.     °dONLNdËP[ö(w6IF FONDid < $4000  {16384}°dONLNdZ<e√+$
  2813. script is Roman so return 0°dONLNd do,(ã6ELSE°dONLNd&n<yΩ+$
  2814. Mscript is international so calculate script id using equation described above
  2815. °dONLNdtÑêD(¨6    Once the °dONLNd}ÑDê⁄),Tscript code has been determined, the routine looks at the the Script Manager globals°dONLNd“êúW(π6    FontForce°dONLNd€ëWùn)? and °dONLNd‡ênú≠)    IntlForce°dONLNdÈë≠ù±)?.°dONLNdΙ∂Ù(“6/If the currently installed script is Roman and °dONLNd©Ùµ3)‹    fontForce°dONLNd#™3∂k)?
  2816.  is true, or °dONLNd0™k∂w)8if °dONLNd3©wµ∂)     intlForce°dONLNd<™∂∂⁄)? is true°dONLNdE∑√(fl6and the routine called °dONLNd\∑√ñ)gwas °dONLNd`∂ñ¬„) _IntlScript°dONLNdk∑„√⁄)M4, then the value returned will be the current system°dONLNd†√œ(Î6:script.  If the installed script is not Roman; the script °dONLNd⁄√œ⁄)˙)code calculated will be returned when the°dONLNd–‹p(¯6routine called was °dONLNdœp€Ω)X _IntlScript°dONLNd"–Ω‹ƒ)M, °dONLNd$œƒ€)    intlForce°dONLNd-–‹Ã)?- is true, and the script code does not equal °dONLNdZ–Ë⁄)…the°dONLNd^‹ËZ(6system script.°dONLNdmÙ*8Once the script code to be returned as been calculated, °dONLNd•Ù⁄(7)a final check is made to be sure that the°dONLNdœ
  2817. À()6+script is installed and enabled.  If it is °dONLNd˙À
  2818. W)≥not; Roman is returned, and °dONLNdW Å)åForced°dONLNdÅ
  2819. ⁄)* is set to false and°dONLNd1
  2820. I(66Default°dONLNd8Iâ)1 is set to true.
  2821. °dONLNdI2A«(]6What’s This Forced Stuff?
  2822. °dONLNdcNZπ*Two Script Manager globals, °dONLNdMπY¯)°    fontForce°dONLNdàN¯Z)? and °dONLNdçMYX)!    intlForce°dONLNdñNXZ⁄)?, are flags that support°dONLNdØ[gà(É6compatibility.  Turning °dONLNd«Zàf«)p    fontForce°dONLNd–[«gK)? on will cause Roman fonts °dONLNdÎ[Kg⁄)Ñto be interpreted as belonging°dONLNd
  2823. gs÷(è6`to the system script.  This provides compatibility for applications that hard-code font numbers.°dONLNdkãH*;For example, the Arabic script interface system provides a °dONLNd¶Hã⁄(ßfcdev which lets a user turn°dONLNd¬ãóW(¥6    fontForce°dONLNdÀåWòfl)? on.  When a user does this, °dONLNdËåflò⁄)à1any Roman fonts will be mapped to an Arabic font.°dONLNdò§q(¿6NNote this is only a partially effective measure since the user still does not °dONLNdiòq§⁄(¿èhave complete control°dONLNd§∞L(Ã6 over fonts.°dONLNdãΩ…Ã*'It should also be noted that if a user °dONLNd≤ΩÃ…„)¥sets °dONLNd∑º„»")    fontForce°dONLNd¿Ω"…⁄)?% on via the cdev, values returned for°dONLNdÊ ÷ë(Ú6fonts with family IDs in °dONLNdˇ ë÷E)y the range $0002 to $3FFF (Roman °dONLNd…E’o)¥'FOND'°dONLNd% o÷⁄)* ID range) may vary.°dONLNd;÷‚X(˛6DThis is not a good feature for applications that allow mixed text.  °dONLNd÷X‚⁄(˛vTo avoid this problem, an°dONLNdô„Ô§( 6application can turn the °dONLNd≤‚§Ó„)å    fontForce°dONLNdª„„Ôr)? flag off before calling °dONLNd‘‚rÓΔ)è _Font2Script°dONLNd‡„ΔÔ–)T °dONLNd·„–Ô⁄)
  2824. or°dONLNd‰Ô˚e(6 _FontScript°dONLNdÔe¸Ω)ML.  The flag value should be saved before turning it off, and restored later.°dONLNd<    /(16The °dONLNd@/n)    intlForce°dONLNdI    n)? flag determines how the call °dONLNdgC)ñ    IUGetIntl°dONLNdp    C⁄)? behaves.  If this flag is on,°dONLNdè!W(>6    IUGetIntl°dONLNdòW"L)?0 will always return the international resources °dONLNd»L"P)ı(°dONLNd…P!z)'itlx'°dONLNdœz"ß)* where °dONLNd÷ß!Æ)-x°dONLNd◊Æ"⁄) is 0-2)°dONLNd‡#/„(K6*corresponding to the system script.  When °dONLNd    
  2825. "„.")À    intlForce°dONLNd    #"/V)?
  2826.  is off, the °dONLNd     #V/⁄)4font in the current port will°dONLNd    >/;Î(W6)be used to determine which international °dONLNd    g/Î;⁄)”.resources will be returned.  This flag lets an°dONLNd    ñ;Gr(c6Lapplication control what  date formats, sorting routines, etc. will be used.°dONLNd    „S_„*+For that reason, before calling any of the °dONLNd
  2827. S„_⁄)À5international utility routines or using the binary to°dONLNd
  2828. D`l(à64decimal routines, an application should verify that °dONLNd
  2829. x_k7)ÓthePort°dONLNd
  2830. `7lN)1 and °dONLNd
  2831. Ñ_Nk∑)thePort^.txFont°dONLNd
  2832. ì`∑l⁄)i are set°dONLNd
  2833. úmyi(ï6correctly, or that °dONLNd
  2834. Ølix®)Q    intlForce°dONLNd
  2835. ∏m®yÚ)? is set properly. ◊4◊˘
  2836. (Ï62) of 4(ÏÇFonts and the Script Managerˇ!Ë◊#ˇ ˇˇˇˇ#◊ 
  2837. IR,Times
  2838. .+Z-Developer Support Center(-Û    June 1989 /X/
  2839. °dONLNd)<5æ(QZLet’s Look at a Picture°dONLNdB<NÓ*&The flowchart in Figure 1 illustrates °dONLNd>BÓNA)≤the operation of ,
  2840. Courier°dONLNdOAAMé)S _FontScript°dONLNdZBéNó)M, °dONLNd\AóM‰)     _IntlScript°dONLNdgB‰N˛)M, and°dONLNdmN<Zê(wZ _Font2Script°dONLNdyOê[Ó)T, and how they °dONLNdàOÓ[•)^!are affected by the global flags °dONLNd©N•Z‰)∑    fontForce°dONLNd≤O‰[˛)? and°dONLNd∑[<g{(ÑZ    intlForce°dONLNd¿\{h)?.†Ç°ñ °ö
  2841. ∂Δ]
  2842.     €îR˙°dONLNdˇˇ+î9 Forced = F
  2843. °dONLNdˇˇ(≈, Default = F†ó
  2844. ìqn0¥Ãa†å°ñ °öW
  2845. ‚ÛÚѰdONLNdˇˇ(Ȉ/Map special font numbers 0 and 1 to System and °dONLNdˇˇ+,Application fonts†ó
  2846. ìqn0‡¯à†ç†å°ñ °öˇ˝
  2847. G£O›°dONLNdˇˇ+â\Get script code†ó
  2848. ìqn0CûT‡†ç†å°ñ °öˇ˝
  2849. GòO÷°dONLNdˇˇ(M°script = Roman†ó
  2850. ìqn0CêT›†ç†å°ñ °ö&
  2851. ≤.¬p°dONLNdˇˇ+êkscript = system script
  2852. °dONLNdˇˇ+smgrForced = T†ó
  2853. ìqn0Æ# }†ç°ñ °ö
  2854. +ôC⁄°dONLNdˇˇ+lqscript = Roman
  2855. °dONLNdˇˇ+ Forced = F
  2856. °dONLNdˇˇ(A© Default = T†ó
  2857. ìqn0&êN‹†å°ñ °ö!
  2858. 
  2859. 'g°dONLNdˇˇ(,script installed and °dONLNdˇˇ+enabled?†ó
  2860. ìqn"††°§
  2861. 
  2862. "¸HÃ##4##4Í##ÃÍ#†£
  2863. ìqn#Ã#4#4Í#Ã͆°†ç†å°ñ °ö
  2864. $)[°dONLNdˇˇ(-International 
  2865. °dONLNdˇˇ+ font?†ó
  2866. ìqn"††°§
  2867. 
  2868. "    >”##-##,Í##‘Î#†£
  2869. ìqn#”#-#,Í#‘Ά°†ç°ñ °ö5
  2870. Çáí°dONLNdˇˇ+baIntlScript call AND IntlForce 
  2871. °dONLNdˇˇ(êôAND (script ≠ system script) ?†ó
  2872. ìqn"ãᆆ°§
  2873. 
  2874. "i¬≈"##;"##;fi##≈fi#†£
  2875. ìqn#≈"#;"#;fi#≈fi†°†å°ñ °ö
  2876. ÅrꈰdONLNdˇˇ(áü
  2877. FontForce OR
  2878. °dONLNdˇˇ(èÖ!(IntlScript call AND IntlForce) ?†ó
  2879. ìqn"ã{††°§
  2880. 
  2881. "fµΔ%##:$##9‹##«€#†£
  2882. ìqn#Δ%#:$#9‹#«€†°†ç†å"’:††°§t’:fi?fi=’:’=’?fi=
  2883. "fi=˝˜######˛    #Ñ
  2884. îrîr†£
  2885. ìqnÑ
  2886. îrîr†°"Õ=†ç†å";††°§t;
  2887. @
  2888. =;=@
  2889. =
  2890. "
  2891. =˛˜######˝    #Ñ
  2892. îrîr†£
  2893. ìqnÑ
  2894. îrîr†°"ˆ= †ç†å"¥††°§
  2895. "jJ# ##†£
  2896. ìqn"j#    #################################†°†å"8憆°§t8æA¬A¿8æ8¿8¬A¿
  2897. "A¿˛˜######˛    #Ñ
  2898. îrîr†£
  2899. ìqnÑ
  2900. îrîr†°":¿˛†ç†ç†å"¬††°§
  2901. "≥#Û##†£
  2902. ìqn"˚#¯#˜#¯#¯#˘#˙#˙#˚#˚#¸#¸#˛#˝#˛#ˇ#ˇ#ˇ##˝#ˇ###ˇ###########†°†å"9≤††°§t9≤B∑Bµ9≤9µ9∑Bµ
  2903. "Bµ˝˜######˛    #Ñ
  2904. îrîr†£
  2905. ìqnÑ
  2906. îrîr†°";µ˛†ç†ç†å"^≤††°§t^≤h∑hµ^≤^µ^∑hµ
  2907. "hµ˝ˆ######˛
  2908. îrîr†£
  2909. ìqnÑ
  2910. îrîr†°"Uµ    †ç†å"]ø††°§t]øfƒf¡]ø]¡]ƒf¡
  2911. "f¡˛˜######˝    #Ñ
  2912. îrîr†£
  2913. ìqnÑ
  2914. îrîr†°"S¡
  2915. †ç°ñ °öˇ˝
  2916. iw°dONLNdˇˇ(kyes†ó°ñ °öˇ˝
  2917.  °dONLNdˇˇ(
  2918. no†ó°ñ °öˇ˝
  2919. Äáè°dONLNdˇˇ+vlyes†ó°ñ °öˇ˝
  2920. Şà °dONLNdˇˇ(áyes†ó†å
  2921. ìqn"ÚD††°§˝tÚD¸I¸FÚDÚFÚI¸F
  2922. "¸F˛ˆ######˝
  2923. îrîr†£
  2924. ìqnÑ
  2925. îrîr†°"»F*†ç†å"◊µ††°§˝
  2926. "±µ&###j##†£
  2927. ìqn"±µ####################################################################†°†å"Ú=††°§˝tÚ=¸A¸?Ú=Ú?ÚA¸?
  2928. "¸?˛ˆ######˛
  2929. îrîr†£
  2930. ìqnÑ
  2931. îrîr†°"Ù?˛†ç†ç†å"÷√††°§˝
  2932. "∞√&##Ò#®#Ú#†£
  2933. ìqn"∞√###################ˇ#ˇ##ˇ#˛#˛##ˇ#ˇ#˛#ˇ#˝#˛#˛#˝#˝#¸#¸#¸#¸#˚#˚#˚#˝#˛#˙#¸#˚#˚#¸#¸#˝#˝#˝#˝#˛#˝#ˇ#˛#ˇ##ˇ#˛#ˇ##ˇ#ˇ#ˇ##†°†å"ÛL††°§˝tÛL¸P¸NÛLÛNÛP¸N
  2934. "¸N˛˜######˛    #Ñ
  2935. îrîr†£
  2936. ìqnÑ
  2937. îrîr†°"ÙNˇ†ç†ç°ñ °öˇ˝
  2938. ≤®∫≤°dONLNdˇˇ(∏™no†ó°ñ °öˇ˝
  2939. ∞…∏”°dONLNdˇˇ(∑Àno†ó†å
  2940. ìqn"^E††°§˝t^EdKdH^E^H^KdH
  2941. "dH˝˙######˝#Ñ
  2942. îrîr†£
  2943. ìqnÑ
  2944. îrîr†°"(H6†ç°ñ °öˇ¸
  2945. }à°dONLNdˇˇ(no†ó†å
  2946. ìqn"∞††°§¸
  2947. "|4#
  2948. ##†£
  2949. ìqn"|##############################†°†å"∏††°§¸t∏$º$∫∏∫º$∫
  2950. "$∫˛˚######˛#Ñ
  2951. îrîr†£
  2952. ìqnÑ
  2953. îrîr†°#˚†ç†ç°ñ °öˇ˝
  2954. e;m]°dONLNdˇˇ(l=RETURN†ó†å
  2955. ìqn"Rø††°§˝
  2956. "Oø##Ú#§#Û##†£
  2957. ìqn"Oø#####ˇ#ˇ##˛#ˇ#˛###˛#˛#ˇ#˛#˛#˝#˝#¸#˝#¸#¸#˚#˚#˚#˚#˝#˝#˚#˙#˚#˝#¸#¸#¸#¸#˛#˝#˝#ˇ#˛#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#˝###ˇ#####†°†å"]J††°§˝t]EbJbH]J]H]EbH
  2958. "bH˚##˛##˝###Ñ
  2959. îrîr†£
  2960. ìqnÑ
  2961. îrîr†°"`H˝†ç†ç°ñ °öˇ˝
  2962. ,74E°dONLNdˇˇ(29yes†ó°ñ °öˇ˝
  2963. 
  2964. î/úI°dONLNdˇˇ(ö1START†ó†å
  2965. ìqn"©9††°§˝t©9≤=≤;©9©;©=≤;
  2966. "≤;˛˜######˛    #Ñ
  2967. îrîr†£
  2968. ìqnÑ
  2969. îrîr†°"°;†ç†å"ä)††°§˝
  2970. "ä9##†£
  2971. ìqn"ä#########################†°†å"†E††°§˝t†=´E´A†E†A†=´A
  2972. "´Aı##¸##¸## #Ñ
  2973. îrîr†£
  2974. ìqnÑ
  2975. îrîr†°"õA†ç†ç†å"ã\††°§˝
  2976. "ãÖ◊#Ô#†£
  2977. ìqn"ãÖ˛#˚#˚#˚#¸#˝#¸#¸#˛#˝#˝#˛#˛#˛#˛##ˇ#ˇ#˛#˛#˛##ˇ#ˇ##†°†å"°I††°§˝t°I¨N¨K°I°K°N¨K
  2978. "¨K˛ı######˝ #Ñ
  2979. îrîr†£
  2980. ìqnÑ
  2981. îrîr†°"úK†ç†ç†É
  2982. IR
  2983. °dONLNd¬[«gr(ÉÂFigure 1–Operation Flowchart ◊X◊
  2984. (ÏZFonts and the Script Manager(Ï3) of 4ˇŒ◊#ˇ ˇˇˇˇ#◊ 
  2985. IR,Times
  2986. .+6-Macintosh Technical Notes /4/˘
  2987. °dONLNd)5Ç*$Further Reference: T4T˘°dONLNd6*B.+
  2988. •°dONLNd6<Bç)Inside Macintosh°dONLNd%6çB)Q3, Volume I-493, The International Utilities Package°dONLNdYB*N.(jH•°dONLNd[B<Nç)Inside Macintosh°dONLNdkBçN>)Q", Volume V-293, The Script Manager°dONLNdéN*Z.(vH•°dONLNdêN<Zç)Inside Macintosh°dONLNd†NçZÉ)Q3, Volume V-287, The International Utilities Package ◊4◊˘
  2989. (Ï64) of 4(ÏÇFonts and the Script Managerˇí◊#ˇ ˇˇˇˇ#◊†Ç 
  2990. /ZÅ#
  2991.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  2992. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  2993. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  2994. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  2995. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  2996.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  2997. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  2998. IR.°dONLNdn<Å/(õZInternational Resource Q&As
  2999. °dONLNdÄ<èZ*Text°dONLNd"Äoè˛(´çM.TX.IntlRsrc.Q&As
  3000. °dONLNd5õ<ßt(√Z Revised by:°dONLNdAõÑߡ)HDeveloper Support Center°dONLNdZõæß˛(√‹ October 1992°dONLNdgß<≥q(œZ Written by:°dONLNdsßÑ≥ˇ)HDeveloper Support Center°dONLNdåßæ≥˛(œ‹ October 1990°dONLNdôø<À⁄(ÁZThis Technical Note contains a °dONLNd∏ø⁄À˛)û9collection of Q&As relating to a specific topic—questions°dONLNdÚÀ<◊†(ÛZGyou’ve sent the Developer Support Center (DSC) along with answers from °dONLNd9À†◊˛(Ûæthe DSC engineers.°dONLNdL◊<„u(ˇZ
  3001. While DSC °dONLNdV◊u„˛)9Lengineers have checked the Q&A content for accuracy, the Q&A Technical Notes°dONLNd£„<Ôq( Z don’t have °dONLNdÆ„qÔ˛)5Qthe editing and organization of other Technical Notes. The Q&A function is to get°dONLNdÔ<˚Ÿ(Znew technical information and °dONLNdÔŸ˚˛)ù6updates to you quickly, saving the polish for when the°dONLNdU˚<(#Z,information migrates into reference manuals.°dONLNdÇ<k*:Q&As are now included with Technical Notes to make access °dONLNdºk˛(;âto technical updates easier for°dONLNd‹<+.(GZ/you. If you have comments or suggestions about °dONLNd .+˛)Ú*Q&A content or distribution, please let us°dONLNd6+<7\(SZknow °dONLNd;+\7˛) Iby sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical°dONLNdÖ7<Ci(_Z9questions about Q&A content to DEVSUPPORT for resolution.°dONLNdøO<[«*NNew Q&As and Q&As revised this month are marked with a bar in the side margin."n  ÜXÜ
  3002. °dONLNdÄ<èâ*41Determining the language being used to enter text
  3003. °dONLNd@è<õb* Written:°dONLNdIèàõ≤)L11/20/90°dONLNdRõ<ßÅ(√ZLast reviewed:°dONLNdaõàß¶)L8/1/92°dONLNdh≥<øH(€ZIs °dONLNdk≥Hø˛) Xthere a way to tell what language is being used on the Macintosh? I know how to find the°dONLNdƒø<ÀÊ(ÁZ[script and other international items, but the language being spoken would be a very useful °dONLNdøÊÀ˛(Áthing°dONLNd%À<◊g(ÛZto know.°dONLNd.◊<„N* ___°dONLNd2Ô<˚¡*MIt depends on what you mean by “language.” It’s impossible to determine what °dONLNdÔ¡˚˛(fl language the°dONLNdå˚<S(#Zuser °dONLNdë˚S˛)Xis typing in without doing a high-level analysis of what is being typed, as you probably°dONLNdÍ<[(/Zknow.°dONLNd<+m*One way °dONLNd¯m+˛)1Lthat’s been suggested in the past is to check on the current KCHR by calling°dONLNdE+<7è(SZBGetScript with an smScriptKeys verb. This returns the resource ID °dONLNdá+è7˛(S≠of the currently active°dONLNdü7<C·(_ZPKCHR. All international systems come with a U.S. KCHR and possibly others, such °dONLNdÔ7·C˛(_ˇas the°dONLNdˆC<O‚(kZNRomaji and Kana KCHRs in the Japanese systems and the alternative Roman KCHRs °dONLNdDC‚O˛(kin the°dONLNdKO<[≠(wZKvarious German and French systems. The thought was that the user will most °dONLNdñO≠[˛(wÀlikely choose the°dONLNd®[<gó(ÉZDU.S. KCHR to type in English, and choose the French KCHR to type in °dONLNdÏ[óg˛(ɵFrench. One problem°dONLNdg<s9(èZ:with this is that it isn’t necessarily true. You can type °dONLNd:g9s˛)˝$English with the French KCHR and you°dONLNd_s<Ö(õZ?can type French with the U.S. KCHR, and many people do. A much °dONLNdûsÖ˛(õ£larger problem is that the°dONLNdπ<ã\(ßZ;KCHR IDs aren’t standardized within a script system range. °dONLNdÙ\ã˛(ßz Because Apple defines a range of°dONLNd    ã<óè(≥Zresource IDs for °dONLNd    &ãèó˛)SLeach script system for the international resources, you can tell what script°dONLNd    só<£ú(øZAsystem a KCHR is for, and you can even match up the KCHR ID with °dONLNd    ¥óú£˛(ø∫the standard KCHR ◊X◊
  3004. (ÏZInternational Resource Q&As(Ï1) of 5ˇ°¿Ù%%DSIDICT:_cv
  3005. currentdict /bu known {bu}if
  3006. userdict /_cv known not{userdict /_cv 30 dict put}if
  3007. _cv begin
  3008. /bdf{bind def}bind def
  3009. currentscreen/cs exch def/ca exch def/cf exch def
  3010. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3011. /ss{//cf //ca //cs setscreen}bdf
  3012. /stg{ss setgray}bdf
  3013. /strgb{ss setrgbcolor}bdf
  3014. /stcmyk{ss cvcmyk}bdf
  3015. /min1{dup 0 eq{pop 1}if}bdf
  3016. end
  3017. currentdict /bn known {bn}if
  3018. †øË◊#ˇ ˇˇˇˇ#◊ 
  3019. IR,Times
  3020. .+6-Macintosh Technical Notes /4/˘
  3021. °dONLNd)£*RIDs that Apple defines, but there’s nothing wrong with someone creating their own °dONLNdR£)⁄(E¡KCHR and°dONLNd[)5Ë(Q6,giving it any ID they want, as long as it’s °dONLNdá)Ë5⁄)–1in the proper range for the script system they’ve°dONLNdπ5Afi(]6/written it for. If that’s the currently active °dONLNdË5fiA⁄)Δ2KCHR, its resource ID tells you what script system°dONLNdAM¢(i6Vit’s for, but it won’t tell you anything about what language it was intended for. For °dONLNdqA¢M⁄(i¿ this reason,°dONLNd~MYº(u6 this method is frowned upon now.°dONLNdüeq_*HIn fact, there really is no reliable way of knowing the language that’s °dONLNdÁe_q⁄(ç}being used. The best you°dONLNdq}Ã(ô6[can do currently is to find out what the system is localized for. This is done by grabbing °dONLNd[qÃ}⁄(ôÍthe°dONLNd_}âi(•6vers resource ID °dONLNdp}iâ⁄)QL1 from the System file. In this resource is what was called the country code°dONLNdΩâïÃ(±6](the term “country code” is obsolete, in favor of “region code”) which indicates what region °dONLNdâÃï⁄(±Íthe°dONLNdï°x(Ω6Fsystem is localized for. These region codes are defined in Packages.p °dONLNddïx°⁄(Ωñin MPW, and have°dONLNdu°≠Ô(…6,names like verUS and verFrance and the like.°dONLNd¢π≈∞*JThere’s another way that you might want to consider. One of the GetScript °dONLNdÏπ∞≈⁄(·Œverbs is°dONLNdı≈—†(Ì6smScriptLang. This returns °dONLNd≈†—⁄)à@the language code of the specified script system for the current°dONLNdQ—›A(˘6system. °dONLNdY—A›⁄))QIf you pass smRoman as the script code to GetScript, it’ll return langFrench on a°dONLNd´›Ⱥ(6French system, langGerman on °dONLNd»›ºÈ⁄)§1a German system, langEnglish on a U.S. or U.K. or°dONLNd˙Èıî(6NAustralian system, and so forth. If you pass smJapanese as the script code to °dONLNdHÈîı⁄(≤GetScript, it’ll°dONLNdYı’(6]return langJapanese. Interestingly, if you pass smRoman as the script code to GetScript when °dONLNd∂ı’⁄(Ûa°dONLNd∏
  3022. ô()6Japanese script system is °dONLNd“ô
  3023. ⁄)Å?running, it’ll return langEnglish. All non-Roman script systems°dONLNd
  3024. 2(565return langEnglish if you pass smRoman as the script °dONLNdG
  3025. 2⁄(5Pcode to GetScript. The language°dONLNdg%±(A6Sconstants are in Language.p in MPW. You’ll probably what to combine this GetScript °dONLNd∫±%⁄(Aœ    call with°dONLNdƒ%1î(M6Ua call to GetEnvirons to find out what the currently active script is. It might look °dONLNd%î1⁄(M≤something like°dONLNd(1=,(Y6this:,
  3026. Courier
  3027.     °dONLNd.IT˛*.(* Get the currently-active keyboard script *)°dONLNd]S^Ù*
  3028. ,keyboardScript := GetEnvirons (smKeyScript);°dONLNdägrb*B(* Now get the language that the keyboard script corresponds to *)°dONLNdÕq|5*
  3029. 9languageCode := GetScript (keyboardScript, smScriptLang);
  3030. °dONLNdáìÆ*In summary, there’s no system °dONLNd%áÆì⁄)ñ@support for retrieving the language that the user is typing, nor°dONLNdfìü«(ª6\is there any reliable support for retrieving the language related to any KCHR. But, you can °dONLNd¬ì«ü⁄(ªÂfind°dONLNd«ü´p(«6the region code of °dONLNd⁄üp´⁄)XKthe active system, and you can find the language associated with the active°dONLNd    &´∑I(”6Ascript. Hopefully, that’s enough information to be useful to you.
  3031. °dONLNd    hœfie*'2RelString & EqualString vs International Utilities
  3032. °dONLNd    õfiÍ>* Written:°dONLNd    §fidÍà)L1/25/91°dONLNd    ¨Íˆ](6Last reviewed:°dONLNd    ªÍdˆÇ)L8/1/92°dONLNd    ¬5(*6What °dONLNd    «5⁄)Ris the difference between RelString and the EqualString? What does DTS suggest its°dONLNd
  3033. Ã(66NMacintosh developers use when sorting? Or do you suggest having an option for °dONLNd
  3034. hÃ⁄(6Íthe°dONLNd
  3035. l&l(B6international sort?°dONLNd
  3036. Ä&2** ___°dONLNd
  3037. Ñ>J *6RelString and EqualString are mainly intended for the °dONLNd
  3038. ∫> J⁄(f>#File Manager. The File Manager uses°dONLNd
  3039. fiJV∂(r6Pthem for quick-and-dirty string comparison so that it knows how to return files °dONLNd .J∂V⁄(r‘ordered°dONLNd 6Vbê(~6alphabetically when you °dONLNd NVêb⁄)xCuse an indexed File Manager routines and so that it can detect file°dONLNd íbn5(ä68name collisions. Beyond that, RelString and EqualString °dONLNd  b5n⁄(äS"aren’t localizable and they’re not°dONLNd ÌnzK(ñ6 extensible.°dONLNd ˘Üí≠*WThe International Utilities string comparison routines are localizable and extensible. °dONLNd PÜ≠í⁄(ÆÀThey use°dONLNd Yíûï(∫6information in the active °dONLNd síïû⁄)}@'itl2' resource to determine how the characters are sorted. Most°dONLNd ¥û™E(Δ6
  3040. localized °dONLNd æûE™⁄)-Osystems come with their own 'itl2' resource, and so string comparisons are done ◊4◊˘
  3041. (Ï62) of 5(ÏÇInternational Resource Q&Asˇ◊#ˇ ˇˇˇˇ#◊ 
  3042. IR,Times
  3043. .+Z-Developer Support Center(-Ê October 1992 /X/
  3044. °dONLNd<)Ê(EZ^correctly for the region that the system is localized for. RelString and EqualString stay the °dONLNd^Ê)˛(Esame°dONLNdc)<5J(QZ8for all these regions, and so you’ll probably find some °dONLNdõ)J5˛(Qh#cases in which strings are compared°dONLNdø5<A≈(]Zincorrectly by these routines.°dONLNdfiM<Y}*?One important place where RelString and EqualString don’t work °dONLNdM}Y˛(uõvery well is with the new°dONLNd7Y<eã(ÅZcharacters in the °dONLNdIYãe˛)OJextended Macintosh character set. When the LaserWriter was introduced, the°dONLNdîe<q∑(çZLaserWriter fonts used °dONLNd´e∑q˛){9the extended Macintosh character set which added many new°dONLNdÂq<}(ôZ-characters, including several new upper-case °dONLNdq}˛)€0characters with diacriticals. In system software°dONLNdC}<â∏(•ZJversion 6.0.4, the International Utilities were updated to take advantage °dONLNdç}∏â˛(•÷ of these new°dONLNdöâ<ï˙(±Z(characters. For example, the upper case °dONLNd¬â˙ï˛)æ6“E” with a grave accent first appeared in the extended°dONLNd˘ï<°ú(ΩZGMacintosh character set. With 6.0.4, the lower and upper case “E” with °dONLNd@ïú°˛(Ω∫a grave accent were°dONLNdT°<≠Ë(…Z"considered to be equal in primary °dONLNdv°Ë≠˛)¨5ordering, and unequal in secondary ordering, which is°dONLNd¨≠<πû(’ZKcorrect. But RelString and EqualString, even today, still think in the old °dONLNd˜≠ûπ˛(’ºMacintosh character°dONLNd π<≈È(·ZXset, so they think that lower and upper case “E” with a grave accent have nothing to do °dONLNdcπÈ≈˛(·with°dONLNdh≈<—–(ÌZ!each other, and that’s not right.°dONLNdä›<Èß*IBecause the RelString and EqualString algorithms are more crude than the °dONLNd”›ßÈ˛(≈string comparison°dONLNdÂÈ<ı∑(ZNroutines in the International Utilities, RelString and EqualString should win °dONLNd3È∑ı˛(’races with the°dONLNdBı<{(ZInternational °dONLNdPı{˛)?KUtilities string comparison routines hands down. The File Manager uses them°dONLNdú<
  3045. ø()ZPpartly for this reason, and partly because RelString and EqualString don’t need °dONLNdÏø
  3046. ˛()›
  3047. access to the°dONLNd˙
  3048. <√(5ZM'itl2' resource, which is usually pretty big. Normally, File Manager sorting °dONLNdG
  3049. √˛(5·isn’t critical°dONLNdV<%d(AZanyway °dONLNd]d%˛)(Ybecause it’s either irrelevant, or it can easily be cleaned up by using the International°dONLNd∑%<1(MZSUtilities string comparison routines. The Standard File package, for example, uses °dONLNd
  3050. %1˛(Mthe°dONLNd1<=Ω(YZUInternational Utilities string comparison routines to order file and folder names in °dONLNdc1Ω=˛(Y€its list so that°dONLNdt=<I{(eZGthe list is ordered correctly regardless of the system it’s running on.°dONLNdºU<a]*X-Ref:°dONLNd√a<mo* =Inside Macintosh Volume VI, page 14-82, “The 'itlm' Resource”
  3051. °dONLNdy<àè*/Macintosh PRAM’s MachineLocation dlsDelta field
  3052. °dONLNd1à<îb* Written:°dONLNd:ààî¨)L1/25/91°dONLNdBî<†Å(ºZLast reviewed:°dONLNdQîà†¶)L8/1/92°dONLNdX¨<∏—(‘ZRHow is the dlsDelta field in PRAM’s time zone MachineLocation record used and set?°dONLNd´∏<ƒN* ___°dONLNdØ–<‹r* Currently, °dONLNd∫–r‹˛)6Mthe dlsDelta field is not being used by Macintosh system software, nor is its°dONLNd    ‹<ËË(Z$meaning defined. There are plans to °dONLNd    ,‹Ë˲)¨=use it in the future, so it’s important that you preserve its°dONLNd    jË<Ù8(Z7current value if you ever use WriteLocation to set the °dONLNd    °Ë8Ù˛)¸)value of gmtDelta. See the description of°dONLNd    ÀÙ<√(Zthe WriteLocation routine in °dONLNd    ËÙ√˛)á<“WorldWide Development: Guide to System Software,” available°dONLNd
  3053. %< ^((Zon the °dONLNd
  3054. ,^ ˛)"Platest developer CD and from APDA (#M7047/A), for details on getting and setting°dONLNd
  3055. } <è(4ZKgmtDelta while leaving dlsDelta intact. In short, the code looks like this:,
  3056. Courier
  3057.     °dONLNd
  3058. …$</_*    VAR°dONLNd
  3059. —.<9·*
  3060. !        myLocation:     Location;°dONLNd
  3061. Û8<C‹*
  3062.          myGMTDelta:     LongInt;°dONLNd B<MÎ*
  3063. #        tempSignedByte: SignedByte;°dONLNd 8L<WU*
  3064.     :°dONLNd >V<a*
  3065. *    tempSignedByte := myLocation.dlsDelta;°dONLNd i`<k˙*
  3066. &    myLocation.gmtDelta := myGMTDelta;°dONLNd êj<u*
  3067. *    myLocation.dlsDelta := tempSignedByte;
  3068. °dONLNd ªå<õ*&Why 1904 is Macintosh Time base
  3069. °dONLNd €õ<ßb* Written:°dONLNd ‰õàß¶)L9/6/91 ◊X◊
  3070. (ÏZInternational Resource Q&As(Ï3) of 5ˇ∏◊#ˇ ˇˇˇˇ#◊ 
  3071. IR,Times
  3072. .+6-Macintosh Technical Notes /4/˘
  3073. °dONLNd)]*Last reviewed:°dONLNdd)Ç)L8/1/92°dONLNd5AM(]6 The global °dONLNd!5MA⁄)5Nvariable Time contains the number of seconds since midnight, Jan. 1, 1904. Why°dONLNdpAMö(i6was the year 1904 chosen ?°dONLNdãMY** ___°dONLNdèeqê*QThe ability to go back in time is one consideration. You would not want to start °dONLNd‡eêq⁄(çÆthe clock from,°dONLNdq}ï(ô6Ksay, 1984. You also want to go ahead in time a good amount, of course. So, °dONLNd;qï}⁄(ô≥the clock start°dONLNdK}âë(•6Pdate needs to put our current date somewhere in the middle of the clock’s range.°dONLNdúï°ï*QSo what is the clock’s range? Since the clock chip has a four byte counter which °dONLNdÌïï°⁄(Ω≥is incremented°dONLNd¸°≠é(…6Keach second, they had 4,294,967,295 seconds to work with, or approximately °dONLNdG°é≠⁄(…¨136 years. This°dONLNdW≠π[(’6 would make °dONLNdb≠[π⁄)CBthe Macintosh clock run out in 1904+136 = 2040. The maximum value,°dONLNd•π≈A(·69$FFFFFFFF, corresponds to 6:28:15 a.m., February 6, 2040.°dONLNdfl—›*5Given the possible range of years/leap years/nonleap °dONLNd—›⁄)˚+years (every fourth year, but not if at the°dONLNd@›Èå(6end of a century, except °dONLNdY›åÈ⁄)tFat the end of every fourth century, which is a leap year) and the date°dONLNd†Èı≈(6\when the clock will run out (2040) - the “leap year code” in the Macintosh only has to deal °dONLNd¸È≈ı⁄(„with°dONLNdı(64the rule “every fourth year is a leap year” because °dONLNd5ı⁄)Ï,none of the possible Macintosh dates violate°dONLNdb
  3074. ?()6?that rule! Remember, 2000 is evenly divisible by 400, so it IS °dONLNd°?
  3075. ⁄()]!a leap year. 1900 is not. If they°dONLNd√
  3076. ¡(56$started at 1900, they would have to °dONLNdÁ
  3077. ¡⁄)©;use a different algorithm that accounts for “non-leap year”°dONLNd#%Í(A6,leap years. Some other clocks start on 1901.°dONLNdP1=Z*CWhy did they start on 12:00:00, January 1, 1904? Well, it probably °dONLNdì1Z=⁄(Yxhas to do with 1904 being°dONLNd≠=IÀ(e6&the first leap year after a “non-leap °dONLNd”=ÀI⁄)≥3year” leap year (1900). So, the year was chosen for°dONLNdIU≥(q6Omechanical (4 byte limit on number of seconds) and pragmatic (you only want to °dONLNdVI≥U⁄(q—use one°dONLNd^Ua(}67algorithm to figure out the date et al) considerations.°dONLNdñmyä*So, back to the future...°dONLNd∞Öë9*X-Ref:°dONLNd∑ëù * /Chapter 4, “Worldwide Guide to System Software”
  3078. °dONLNdÁµƒŸ*'System 7 and 'itl1' resources
  3079. °dONLNdƒ–>* Written:°dONLNdƒd–à)L9/16/91°dONLNd–‹](¯6Last reviewed:°dONLNd%–d‹Ç)L8/1/92°dONLNd,ËÙ†(6LSystem 7 doesn’t recognize some of my 'itl1' resource changes, such as date °dONLNdxˆÙ⁄(æ abbreviation°dONLNdÖÙ÷(6(length, that are recognized by System 6.°dONLNdÆ ** ___°dONLNd≤$v*The field that you °dONLNd≈v$⁄)^Brefer to is not doing what you want because System 7 introduced an°dONLNd$0(L63expanded 'itl1' resource, with several new fields, °dONLNd;$0⁄)˚(including arrays that contain the proper°dONLNdd0<A(X6@abbreviations of all the months and days. If you look in Inside °dONLNd§0A<⁄(X_Macintosh Volume VI on pages°dONLNd¡<H‡(d6+14-87 thru 14-89 you’ll find a description °dONLNdÏ<‡H⁄)»5of this new resource as well as the rez definition of°dONLNd    "HTö(p6Iit. Note the two new arrays, abbrevDays and abbrevMonths. If you were to °dONLNd    kHöT⁄(p∏ modify these°dONLNd    xT`õ(|6additional fields, you’d see °dONLNd    ïTõ`⁄)ÉBthe date in the finder windows change. (In fact, the abbrev length°dONLNd    ÿ`l=(à6@field does not seem to be used if these new fields are present.)
  3080. °dONLNd
  3081. Ñìí*'8'itl0' resource time1Suff…time8Suff field interpretation
  3082. °dONLNd
  3083. Rìü>* Written:°dONLNd
  3084. [ìdüà)L11/4/91°dONLNd
  3085. cü´](«6Last reviewed:°dONLNd
  3086. rüd´Ç)L8/1/92 ◊4◊˘
  3087. (Ï64) of 5(ÏÇInternational Resource Q&Asˇ ÷◊#ˇ ˇˇˇˇ#◊ 
  3088. IR,Times
  3089. .+Z-Developer Support Center(-Ê October 1992 /X/
  3090. °dONLNd)<5Ø(QZNHow are the 'itl0' resource time1Suff, time2Suff, … to be interpreted? On the °dONLNdN)Ø5˛(QÕGerman system,°dONLNd]5<Aé(]Zthese bytes seem °dONLNdn5éA˛)RKto contain “ Uhr Uhr.” The correct 24-hour time suffix should be a single “°dONLNd∫A<Mö(iZUhr.” How do we °dONLNd AöM˛)^Gknow how many bytes of this 8-character entity are significant? Similar°dONLNdM<Y»(uZWquestion for the mornStr and eveStr: are all 4 characters of each of these significant?°dONLNdjY<eN* ___°dONLNdnq<}Â*VThe time1Suff…time8Suff fields in the 'itl0' resource of all localized systems divide °dONLNdƒqÂ}˛(ôthose°dONLNd }<âÀ(•ZQfields into two sections. The first four bytes (time1Suff through time4Suff) are °dONLNd}Àâ˛(•È    used from°dONLNd%â<ïU(±Z712:00 midnight through one second before noon, and the °dONLNd\âUï˛(±s"last four bytes (time5Suff through°dONLNdï<°O(ΩZ7time8Suff) are used from 12:00 noon through one second °dONLNd∂ïO°˛(Ωm%before midnight. This is to take into°dONLNd‹°<≠Í(…ZTaccount any system that has hours from 00:00:00 through 23:59:59, but has different °dONLNd0°Í≠˛(…time°dONLNd5≠<πp(’Z
  3091. trailers for °dONLNdB≠pπ˛)4Nthe morning and evening hours. I don’t know of any that work this way offhand,°dONLNdëπ<≈¯(·Z'though. The German standard is just to °dONLNd∏π¯≈˛)º3append “Uhr” onto the time, morning or evening, and°dONLNdÏ≈<—?(ÌZ6it’s separated from the time by one space. Any unused °dONLNd"≈?—˛(Ì](bytes just contain zero. For example, if°dONLNdK—<›~(˘ZCthe German time suffix was “Uh”, then the time suffix fields would °dONLNdé—~›˛(˘úcontain a space, “U”, “h”,°dONLNd©›<È”(ZZzero, space, “U”, “h”, and zero. If there’s no time suffix, then all eight bytes are zero.°dONLNdı<8*5The morning string and evening strings are done in a °dONLNd9ı8˛)¸%similar way. Each one holds a maximum°dONLNd_<
  3092. J()Z:of four bytes, and any unused bytes are filled with zeros.°dONLNdö<%Ê*&By the way, you’ll find that a lot of °dONLNd¿Ê%˛)™:time suffixes are filled in with something even though the°dONLNd˚%<1i(MZ
  3093. flags say °dONLNd%i1˛)-Vthat time suffixes aren’t used. This is just localization garbage, which probably will°dONLNd\1<=≠(YZbe cleaned up someday. ◊X◊
  3094. (ÏZInternational Resource Q&As(Ï5) of 5ˇ@◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  3095. /ZÅ#
  3096.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3097. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3098. .^ tK^ tK+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3099. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3100. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3101.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3102. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  3103. IR.°dONLNd{<é˝(®ZInternational Canceling
  3104. °dONLNdç<úZ*Text°dONLNdçQú˛(∏oM.TE.InternationalCancel
  3105. °dONLNd7®<¥q(–Z Written by:°dONLNdC®Ñ¥¡)H John Harvey°dONLNdO®∏¥˛(–÷
  3106. February 1990°dONLNd]¿<Ãö(ËZFThis Technical Note describes potential problems canceling operations °dONLNd£¿öÃ˙(Ë∏with the Command°dONLNd≥¿˙Ã˛)`-°dONLNd¥Ã<ÿ%(ÙZ0period key sequence and international keyboards. X
  3107. °dONLNd½< Â*4Where Did That Key Go?
  3108. °dONLNd¸<$Ì*RCanceling an operation, from printing to compiling, has always been done with the °dONLNdNÌ$˛(@ key°dONLNdR$<0(LZ+sequence Command-period.  The problem with °dONLNd}$0˛)‚/this is that on some international systems, one°dONLNd≠0<<õ(XZEneeds to hold the Shift key down to produce a period.  Many keyboard °dONLNdÚ0õ<˛(Xπmappings, including°dONLNd<<H
  3109. (dZ,that of the U.S., ignore the Shift key when °dONLNd2<
  3110. H˛)Œ.the Command key is down.  In other words, on a°dONLNdaH<TW(pZ8system where a period (.) is a shifted character (e.g., °dONLNdôHWT˙(puItalian) pressing Command-Shift°dONLNd∏H˙T˛)£-°dONLNdπT<`(|Z*KeyThatMakesAPeriod does not generate the °dONLNd„T`˛)ÿ/ASCII code for a period.  Instead, the keyboard°dONLNd`<li(àZ<mapping software generates the ASCII code for the unshifted °dONLNdO`il˛(àá character.  If an application is°dONLNdpl<xù(îZHlooking for Command-period to cancel some time intensive operation, and °dONLNd∏lùx˛(îªan international user°dONLNdŒx<ÑŒ(†Ztypes the shifted key sequence °dONLNdÌxŒÑ˛)í;that normally produces a period along with the Command key,°dONLNd)Ñ<ê¨(¨ZRthe application is going to miss that request unless it takes special precautions.
  3111. °dONLNd|®<∑*' A Bit Confusing (to me at least)
  3112. °dONLNdù√<œÀ*RThe solution to this potential international disaster is to strip the Command key °dONLNdÔ√Àœ˛(ÎÈ
  3113. out of the°dONLNd˙œ<€Æ(˜Zmodifiers, and then run °dONLNdœÆ€˛)rBthe key code back through the keyboard mapping software.  The trap,
  3114. Courier°dONLNdU€<Á{(Z    _KeyTrans°dONLNd^‹{Ë)?" makes this procedure very easy.  °dONLNdÄ€Á[)°    _KeyTrans°dONLNdâ‹[Ëy)? takes °dONLNdê‹y˲)as parameters a pointer to a°dONLNd≠Ë<Ùf(Z'KCHR'°dONLNd≥Èfıò)*
  3115.  resource °dONLNdΩÈòı˛)2@(see M.TB.KeyMapping), a word which contains the keycode and the°dONLNd˛ı<N(Z;modifier bits, and a word which serves as a state variable.°dONLNd:<Ì*#One note on the result returned by °dONLNd]
  3116. Ì,)±    _KeyTrans°dONLNdf,5)?. °dONLNdh5;)     °dONLNdi;è)Inside Macintosh°dONLNdyè˛)T, Volume V-195, The°dONLNdç<&¡(BZRToolbox Event Manager, states, “ASCII 1 is the ASCII value of the first character °dONLNdfl¡&˛(Bfl generated by°dONLNdÏ&<2ª(NZPthe key code parameter.”  This statement is followed by an illustration (Figure °dONLNd<&ª2˙(NŸ 7 on page V°dONLNdG&˙2˛)?-°dONLNdH2<>y(ZZ 195) which °dONLNdS2y>˛)=Gshows ASCII 1 as the low byte of the high word in the long word result.°dONLNdú><Jô(fZGAlthough this statement and the accompanying illustration are correct, °dONLNd„>ôJ˛(f∑they have mislead a°dONLNd˜J<V—(rZnumber of people (me for one).°dONLNdb<n    *-It is dangerous to expect the character code °dONLNdCb    n˛)Õ3in one particular word of the long word result.  In°dONLNdwo<{À(óZfact, the architecture of the °dONLNdïnÀz
  3117. )è    _KeyTrans°dONLNdûo
  3118. {)?+ trap does not specify which word contains °dONLNd…o{˛)Êthe°dONLNdÕ|<à_(§Z:character code in which you might be interested.  This is °dONLNd    |_àû(§} because the °dONLNd    {ûá›)?    _KeyTrans°dONLNd    |›à˛)? trap’s°dONLNd    $à<î#(∞Z0primary purpose is to create a package that can °dONLNd    Tà#î˛)Á*be used to build a key-down event, and the°dONLNd    î<†Î(ºZ#Toolbox Event Manager just doesn’t °dONLNd    ¢îΆ˛)Ø=care about particular keys.  In fact, it is possible to get a ◊X◊
  3119. (ÏZInternational Canceling(Ï1) of 5ˇ°¿Ù%%DSIDICT:_cv
  3120. currentdict /bu known {bu}if
  3121. userdict /_cv known not{userdict /_cv 30 dict put}if
  3122. _cv begin
  3123. /bdf{bind def}bind def
  3124. currentscreen/cs exch def/ca exch def/cf exch def
  3125. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3126. /ss{//cf //ca //cs setscreen}bdf
  3127. /stg{ss setgray}bdf
  3128. /strgb{ss setrgbcolor}bdf
  3129. /stcmyk{ss cvcmyk}bdf
  3130. /min1{dup 0 eq{pop 1}if}bdf
  3131. end
  3132. currentdict /bn known {bn}if
  3133. †ør◊#ˇ ˇˇˇˇ#◊ 
  3134. IR,Times
  3135. .+6-Macintosh Technical Notes /4/˘
  3136. °dONLNd*O* result from ,
  3137. Courier°dONLNd O)é)7    _KeyTrans°dONLNdé*œ)? that contains °dONLNd$œ*⁄)A5character codes in both words.  This is how dead keys°dONLNdZ*6R(R6 are handled.°dONLNdgBN *%But how does one handle a particular °dONLNdåB N⁄)≤:character, specifically a period?  The strategy adopted in°dONLNd«NZ≥(v6[the sample function in this Note is to check both words of the result.  If a period exists °dONLNd"N≥Z⁄(v—    in either°dONLNd,Zf∏(Ç6Qword and the Command key is down, it is counted as a Command-period key sequence.°dONLNd~r~á*Now that everything is °dONLNdïrá~⁄)oGstraight about parameters and results, it’s time to look at some sample°dONLNd›~äO(¶6Acode.  The code fragment which follows ensures that you get that °dONLNd~Oä⁄(¶mperiod regardless of the state°dONLNd=äñ{(≤6of the modifier keys.°dONLNdS¢Æ_*
  3138. MPW Pascal
  3139.     °dONLNd^∫≈1*CONST°dONLNddƒœg*
  3140. C  kMaskModifier = $FE00; {need to strip command key from Modifiers}°dONLNd®ŒŸg*
  3141. C  kMaskVirtualKey = $0000FF00; {get virtual key from event message}°dONLNdÏÿ„ö*
  3142.   kMaskASCII1 = $00FF0000;°dONLNd‚Ì0*
  3143. 8  kMaskASCII2= $000000FF; {get key from KeyTrans return}°dONLNd@ϘÜ*
  3144.   kKeyUpMask  = $0080;°dONLNdWˆÅ*
  3145.   kPeriod = ORD('.');°dONLNdm
  3146. ,*TYPE°dONLNdrö*
  3147.   EventPtr = ^EventRecord;°dONLNdç(3*0FUNCTION CmdPeriod(theEvent: EventPtr): Boolean;°dONLNdæ2='*
  3148. VAR°dONLNd¬<Gê*
  3149.   keyCode     : Integer;°dONLNd€FQY*
  3150.  
  3151.   virtualKey,°dONLNdÈP[J*
  3152.  
  3153.   keyInfo,°dONLNdÙZeJ*
  3154.  
  3155.   lowChar,°dONLNdˇdoO*
  3156.   highChar,°dONLNd ny@*
  3157.   state,°dONLNdxÉê*
  3158.   keyCId      : Longint;°dONLNd-Ççã*
  3159.   hKCHR       : Handle;°dONLNdEñ°1*BEGIN°dONLNdK™µÜ*  CmdPeriod  := FALSE;°dONLNdbæ…è*K  IF ( theEvent^.what = keyDown ) | ( theEvent^.what = autoKey ) THEN BEGIN°dONLNdÆ“›S*?    {see if the command key is down.  If it is, get the ASCII }°dONLNdÓ‹Á5*
  3160. 9    IF  BAND(theEvent^.modifiers,cmdKey) <> 0  THEN BEGIN°dONLNd(˚l*D      virtualKey := BAND(theEvent^.message,kMaskVirtualKey) DIV 256;°dONLNdm˙]*
  3161. A    {strip the virtual key by ANDing the modifiers with our mask}°dONLNdØ5*
  3162. 9      keyCode := BAND(theEvent^.modifiers,kMaskModifier);°dONLNdȺ*
  3163. T      keyCode := BOR(keyCode,kKeyUpMask);  {let KeyTrans think it was a keyup event,°dONLNd>#,*
  3164. this°dONLNdC"-≠*
  3165. Q                                            will keep special dead key processing°dONLNdï,7,*
  3166. from°dONLNdõ6A+*
  3167. 7                                            occurring }°dONLNd”@K¬*
  3168. "    {Finally OR in the virtualKey}°dONLNdˆJUÂ*
  3169. )      keyCode := BOR(keyCode,virtualKey);°dONLNd T_m*
  3170.       state := 0;°dONLNd2hsg*C      keyCId := GetScript( GetEnvirons(smKeyScript), smScriptKeys);°dONLNdv|áÔ*+      {read the appropriate KCHR resource }°dONLNd¢ÜëÍ*
  3171. *      hKCHR := GetResource('KCHR',keyCId); ◊4◊˘
  3172. *?2) of 5(ÏõInternational Cancelingˇ ˛◊#ˇ ˇˇˇˇ#◊ 
  3173. IR,Times
  3174. .+Z-Developer Support Center(-‚
  3175. February 1990 /X/,
  3176. Courier
  3177.     °dONLNd'<2‹(NZ       IF hKCHR <> NIL THEN BEGIN°dONLNd!1<<÷*
  3178. R        { we don't need to lock the resource since KeyTrans will not move memory }°dONLNdt;<F6*
  3179. 2        keyInfo := KeyTrans(hKCHR^,keyCode,state);°dONLNdßE<P◊*
  3180.         ReleaseResource(hKCHR);°dONLNd«O<Zi*
  3181.           END°dONLNd—Y<dn*
  3182.  
  3183.       ELSE°dONLNd‹c<n«*
  3184. O        {if we can't get the KCHR for some reason we set keyInfo to the message°dONLNd,m<xx*
  3185. field.  This°dONLNd:w<Ç÷*
  3186. R         ensures that we still get the Cancel operation on systems where '.' isn't°dONLNdçÅ<åi*
  3187.     shifted.}°dONLNdóã<ñı*
  3188. %        keyInfo := theEvent^.message;°dONLNdΩü<™*+      LowChar := BAND(keyInfo,kMaskASCII2);°dONLNdÈ©<¥@*
  3189. 4      HighChar := BSR(BAND(keyInfo,kMaskASCII1),16);°dONLNdΩ<»^*:      IF ( LowChar = kPeriod ) | (HighChar = kPeriod) THEN°dONLNdZ«<“Õ*
  3190.            CmdPeriod := TRUE;°dONLNdx—<‹d*
  3191.     END;°dONLNdÅ€<ÊZ*
  3192.   END;°dONLNdàÂ<P*
  3193. END;
  3194. °dONLNdç˚<h*MPW C
  3195.     °dONLNdì<€*S#define kMaskModifiers  0xFE00 // we need the modifiers without the command key for°dONLNdÁ<(d*
  3196. KeyTrans°dONLNd'<2‡*
  3197. T#define kMaskVirtualKey 0x0000FF00 //get virtual key from event message for KeyTrans°dONLNdE1<<“*
  3198. #define kUpKeyMask      0x0080°dONLNdd;<F‡*
  3199. T#define kShiftWord      8 //we shift the virtual key to mask it into the keyCode for°dONLNdπE<Pd*
  3200. KeyTrans°dONLNd¬O<Z§*
  3201. H#define kMaskASCII1     0x00FF0000 // get the key out of the ASCII1 byte°dONLNd Y<d§*
  3202. H#define kMaskASCII2     0x000000FF  //get the key out of the ASCII2 byte°dONLNdTc<n6*
  3203. 2#define kPeriod         0x2E // ascii for a period°dONLNdáw<Ç**Boolean CmdPeriod( EventRecord *theEvent )°dONLNd≤Å<åA*
  3204. {°dONLNd¥ï<†Ø*  Boolean  fTimeToQuit;°dONLNdÃü<™õ*
  3205.   short    keyCode;°dONLNd‡©<¥Å*
  3206. A  long     virtualKey, keyInfo, lowChar, highChar, state, keyCId;°dONLNd"≥<æë*
  3207.   Handle   hKCHR;°dONLNd4«<“™*  fTimeToQuit = false;°dONLNdK€<Êü*G  if (((*theEvent).what == keyDown) || ((*theEvent).what == autoKey)) {°dONLNdìÔ<˙Ü*B  // see if the command key is down.  If it is, find out the ASCII°dONLNd÷˘<    *
  3208. )  // equivalent for the accompanying key.°dONLNd
  3209. <*(  if ((*theEvent).modifiers & cmdKey ) {°dONLNd)!<,ü*G    virtualKey = ((*theEvent).message & kMaskVirtualKey) >> kShiftWord;°dONLNdq+<6O*
  3210. 7    // And out the command key and Or in the virtualKey°dONLNd©5<@©*
  3211. I    keyCode    = ((*theEvent).modifiers & kMaskModifiers)  |  virtualKey;°dONLNdÛ?<Jõ*
  3212.     state      = 0;°dONLNdS<^ï*E    keyCId     = GetScript( GetEnvirons(smKeyScript), smScriptKeys );°dONLNdM]<h'*
  3213. /    hKCHR      = GetResource( 'KCHR', keyCId ); ◊X◊
  3214. *hInternational Canceling(Ï3) of 5ˇ÷◊#ˇ ˇˇˇˇ#◊ 
  3215. IR,Times
  3216. .+6-Macintosh Technical Notes /4/˘,
  3217. Courier
  3218.     °dONLNd'2ã*!    if (hKCHR != nil) {°dONLNd1<v*
  3219. F      /* Don't bother locking since KeyTrans will never move memory */°dONLNd_;F*
  3220. 2      keyInfo = KeyTrans(*hKCHR, keyCode, &state);°dONLNdíEP≥*
  3221.       ReleaseResource( hKCHR );°dONLNd≤OZ1*
  3222.     }°dONLNd∏Yd@*
  3223.     else°dONLNd¡cn«*
  3224. #     keyInfo = (*theEvent).message;°dONLNdÂwÇ÷*&    lowChar =  keyInfo &  kMaskASCII2;°dONLNd Åå˘*
  3225. -    highChar = (keyInfo & kMaskASCII1) >> 16;°dONLNd:ãñ*
  3226. 2    if (lowChar == kPeriod || highChar == kPeriod)°dONLNdmï†ï*
  3227.       fTimeToQuit = true;°dONLNdá©¥«*#  }  // end the command key is down°dONLNd´≥æê*
  3228. }  // end key down event°dONLNdƒ«“Ü*return( fTimeToQuit );°dONLNd€—‹*
  3229. }
  3230. °dONLNd›ÛÀ*&What About That Resource
  3231. °dONLNdˆÃ*%The astute observer may have noticed °dONLNdÃ⁄)¥8that the code example requires that you read a resource.°dONLNdU&ó(B6UAlthough this certainly isn’t that big of a deal, it is always nice when you can cut °dONLNd™ó&⁄(Bµ down on disk°dONLNd∑'3}(O6accesses.  In System °dONLNdÃ'}3P)e,7.0 a verb is added that can be used to get °dONLNd¯&P2§)” _GetEnvirons°dONLNd'§3⁄)T  to return a°dONLNd4@}(\6pointer to the current °dONLNd(3}?ß)e'KCHR'°dONLNd.4ß@p)*+.  The verb is defined and used as follows:°dONLNdZLX<(t6Pascal
  3232.     °dONLNdado1*CONST°dONLNdgnyÜ*
  3233.     smKCHRCache =  38;°dONLNd~Çç‡*(    KCHRPtr := GetEnvirons(smKCHRCache);
  3234. °dONLNdßò§!*C
  3235.     °dONLNd©∞ªÜ*#define smKCHRCache 38°dONLNd¿ƒœ€*'    KCHRPtr = GetEnvirons(smKCHRCache);
  3236. °dONLNdË€Á*(Unfortunately, in system software prior °dONLNd€Ás)ÿto 7.0, you must use °dONLNd%⁄sÊ«)É _GetResource°dONLNd1€«Á⁄)T as°dONLNd5ËÙ≈(6demonstrated above to obtain     °dONLNdRË≈Ù )≠ the current °dONLNd^Á Û6)G'KCHR'°dONLNddË6Ù⁄)* resource.  However, since°dONLNdÙl(6 _GetEnvirons°dONLNdãılP)T0 always returns zero when passed a verb it does °dONLNdªıP⁄)‰not recognize, you can build°dONLNdÿ
  3237. ?()6>System 7.0 compatibility into your application without having °dONLNd?
  3238. ⁄()]to check which system software°dONLNd5
  3239. N(56Bis running.  To do this, you could modify the routines as follows:°dONLNdx%1<*Pascal
  3240.     °dONLNd=Hº*TCONST {define our own constant until System 7.0 headers ship.  At that point, if you°dONLNd‘GR:*
  3241. :       have not shipped, you can put in the real constant}°dONLNdQ\§*
  3242.     NewVerb_smKeyCache = 38;°dONLNd,[f'*
  3243. VAR°dONLNd0epr*
  3244.     KCHRPtr : Ptr;°dONLNdCyÑ!*5    KCHRPtr := Ptr(GetEnvirons(NewVerb_smKeyCache ));°dONLNdyÉé
  3245. *
  3246. 1    hKCHR   := NIL;  {set to NIL before starting}°dONLNd´ó¢Ö*I    IF KCHRPtr = NIL THEN BEGIN  {we didn't get the ptr from GetEnvirons}°dONLNdı°¨b*
  3247. B      keyCId := GetScript(GetEnvirons(smKeyScript), smScriptKeys); ◊4◊˘
  3248. *$4) of 5(ÏõInternational Cancelingˇà◊#ˇ ˇˇˇˇ#◊ 
  3249. IR,Times
  3250. .+Z-Developer Support Center(-‚
  3251. February 1990 /X/,
  3252. Courier
  3253.     °dONLNd'<2(NZ+      {read the appropriate KCHR resource }°dONLNd,1<<*
  3254. *      hKCHR := GetResource('KCHR',keyCId);°dONLNdW;<F¥*
  3255.       KCHRPtr := hKCHR^;°dONLNdpE<Pd*
  3256.     END;°dONLNdyY<d‹*     IF KCHRPtr <> NIL THEN BEGIN°dONLNdöc<nÃ*
  3257. P      { we don't need to lock the resource since KeyTrans will not move memory }°dONLNdÎm<x1*
  3258. 1      keyInfo := KeyTrans(KCHRPtr,keyCode,state);°dONLNdw<Çæ*
  3259.       IF hKCHR <> NIL THEN°dONLNd8Å<å◊*
  3260.         ReleaseResource(hKCHR);°dONLNdXã<ñ_*
  3261.     END
  3262. °dONLNd`°<≠E*C
  3263.     °dONLNdbπ<ƒ"*./* again we define our own constant for now */°dONLNdë√<ŒÕ*
  3264. #define NewVerb_smKeyCache 38°dONLNdØ◊<‚x* Ptr KCHRPtr;°dONLNdºÎ<ˆO*7    hKCHR = nil;  /* set this to nil before starting */°dONLNdÙı<@*
  3265. 4    KCHRPtr = (Ptr)GetEnvirons(NewVerb_smKeyCache );°dONLNd)    <•*    IF ( !KCHRPtr ) {°dONLNd?<Ü*
  3266. B      keyCId = GetScript( GetEnvirons(smKeyScript), smScriptKeys);°dONLNdÇ'<2*+      hKCHR   = GetResource('KCHR',keyCId);°dONLNdÆ1<<Ø*
  3267.       KCHRPtr = *hKCHR;°dONLNdΔ;<FZ*
  3268.     };°dONLNdÕO<Zñ*    IF (KCHRPtr) {°dONLNd‡Y<d6*
  3269. 2      keyInfo := KeyTrans(KCHRPtr ,keyCode,state);°dONLNdc<nå*
  3270.       if (hKCHR)°dONLNd$m<x◊*
  3271.         ReleaseResource(hKCHR);°dONLNdDw<ÇU*
  3272.     }
  3273. °dONLNdJ•<±¶*/Further Reference: –X–°dONLNd]≤NæR+
  3274. •°dONLNd_≤`æ±)Inside Macintosh°dONLNdo≤±æL)Q, Volume V, The Script Manager°dONLNdéæN R(Êl•°dONLNdêæ` ±)Inside Macintosh°dONLNd†æ± v)Q%, Volume V, The Toolbox Event Manager°dONLNdΔ N÷R(Úl•°dONLNd» `÷ø)M.TB.KeyMapping ◊X◊
  3275. (ÏZInternational Canceling(Ï5) of 5ˇX◊#ˇ ˇˇˇˇ#◊†Ç 
  3276. /ZÅ#
  3277.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3278. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3279. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3280. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3281. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3282.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3283. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  3284. IR.°dONLNdz<çÀ(ßZ0Changes in International Utilities and Resources
  3285. °dONLNd1å<õZ*Text°dONLNd7ååõ˛(∑™M.TE.IUChanges
  3286. °dONLNdFß<≥t(œZ Revised by:°dONLNdSß≈≥˛(œ„
  3287. March 1988°dONLNd^≥<øq(€Z Written by:°dONLNdj≥ÑøÏ)HPriscilla Oppenheimer°dONLNdÄ≥œø˛(€Ì    July 1987°dONLNdäÀ<◊(ÛZ,The International Utilities package and the °dONLNd∂À◊˛)’.international resources have been changed with°dONLNdÂ◊<„E(ˇZ8System file 4.1 to take advantage of the Script Manager. X°dONLNd    <[*2INTL,     Helvetica°dONLNd"[u) vs. °dONLNd'    uÅ)itl°dONLNd+!<-Y(IZ9In the past, there were two INTL resources in the System °dONLNdd!Y-˛(Iwfile, INTL 0 and INTL 1, which°dONLNdÉ-<9ñ(UZKcontained international formatting options. Starting with System 4.1, itl0 °dONLNdŒ-ñ9˛(U¥and itl1 replace INTL°dONLNd‰9<EÍ(aZ!0 and INTL 1. (INTL 0 and INTL 1 °dONLNd9ÍE˛)Æ<are still included with the System file so that applications°dONLNdBE<Q“(mZthat do a GetResource for them °dONLNdaE“Q˛)ñ@will still find them. Only these erroneous applications that use°dONLNd¢Q<]Õ(yZGetResource will access these °dONLNd¿QÕ]˛)ë=resources now; the System will no longer look at them.) There°dONLNd˛]<i1(ÖZ7can now be a set of international resources (itls) for °dONLNd5]1i˛)ı-each script that is installed. That is, where°dONLNdci<uá(ëZ?once there was one resource type (INTL) with IDs 0 and 1 there °dONLNd¢iáu˛(ë•are now many different°dONLNdπu<Ån(ùZBresource types (itl0, itl1, itl2, itlb, itlc, KCHR) with distinct °dONLNd˚unŞ(ùåresource IDs for the various°dONLNdÅ<çç(©ZIcountries. The U.S. System file uses resource ID 0 for all itl resources.°dONLNdbô<•€*#If your existing application calls °dONLNdÖô€•˛)ü<IUGetIntl to get the appropriate international resource, you°dONLNd¬•<±a(ÕZ9will have no problems under System 4.1. If, however, you °dONLNd˚•a±˛(Õcall GetResource on INTL 0 or°dONLNd±<Ω+(ŸZ1INTL 1 and then modify them, and expect that the °dONLNdJ±+Ω˛)Ô*System will use the modified resource, you°dONLNduΩ<…|(ÂZEwill no longer work correctly. If your application has been released °dONLNd∫Ω|…˛(Âöin the past with a modified°dONLNd÷…<’‚(ÒZ System file to include your own °dONLNdˆ…‚’˛)¶2INTL 0 and/or INTL 1, you may want to release your°dONLNd)’<·(˝Z-application with a modified itl0 and/or itl1.°dONLNdW˘<˚*$!The International Sorting Routine°dONLNdz< *RThe international sorting routine is used to handle cases where letters are equal °dONLNdà˛(9Ë
  3288. in primary°dONLNd◊<)å(EZFordering but different in secondary ordering (e.g., “ä” and “a”). The °dONLNdå)˛(E™routine can also handle°dONLNd5)<5
  3289. (QZ.cases where one character sorts as if it were °dONLNdc)
  3290. 5˛)—1two, or two characters would sort as if they were°dONLNdï5<A’(]Z!one, or even character reversals.°dONLNd∑M<Yl*BPrior to System 4.1, the international sorting routine was stored °dONLNd˘MlY˛(uä starting with the localRtn field°dONLNdY<eI(ÅZof °dONLNdYIe˛)
  3291. XINTL 1. As of System 4.1, this routine is now stored in itl2. An INTL 2 resource is also°dONLNdve<qê(çZincluded with the °dONLNdàeêq˛)TOinternational resources, just for consistency (the System never uses it). It is°dONLNdÿq<}¨(ôZexactly the same as itl2.°dONLNdÚ}<âÎ* !Writing your own sorting routine °dONLNd    }Îâ˛)Ø4can be dangerous if it is not done correctly. Before°dONLNd    Hâ<ï(±ZVattempting to do this, we would highly recommend you check with Apple to determine if °dONLNd    ûâï˛(±we°dONLNd    °ï<°»(ΩZUare already doing one for the language of interest. We plan to do many international °dONLNd    ˆï»°˛(ΩÊ versions of°dONLNd
  3292. °<≠(…Z,System file 4.1, and most developers’ needs °dONLNd
  3293. .°≠˛)’0will be met by these. A new policy at Apple will ◊X◊
  3294. (ÏZ0Changes in International Utilities and Resources(Ï1) of 2ˇ°¿Ù%%DSIDICT:_cv
  3295. currentdict /bu known {bu}if
  3296. userdict /_cv known not{userdict /_cv 30 dict put}if
  3297. _cv begin
  3298. /bdf{bind def}bind def
  3299. currentscreen/cs exch def/ca exch def/cf exch def
  3300. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3301. /ss{//cf //ca //cs setscreen}bdf
  3302. /stg{ss setgray}bdf
  3303. /strgb{ss setrgbcolor}bdf
  3304. /stcmyk{ss cvcmyk}bdf
  3305. /min1{dup 0 eq{pop 1}if}bdf
  3306. end
  3307. currentdict /bn known {bn}if
  3308. †øê◊#ˇ ˇˇˇˇ#◊ 
  3309. IR,Times
  3310. .+6-Macintosh Technical Notes /4/˘
  3311. °dONLNd)L*    now make °dONLNd    L)⁄)4Sit possible to license foreign versions of the System file from Software Licensing.°dONLNd])5è(Q6MContact Software Licensing at (408) 973-4667 for more information about this.°dONLNd´MY<*$0Error in APDA draft of Inside Macintosh Volume V°dONLNd›eqC*    There is °dONLNdÊeCqΩ)+Man error in the APDA draft of the International Utilities Package chapter of °dONLNd3eΩq⁄(ç€Inside°dONLNd:q}|(ô6Macintosh Volume V°dONLNdLq|}ú)dB. It says that there is a flag in the Script Manager globals that °dONLNdéqú}⁄(ô∫
  3312. overrides the°dONLNdú}âµ(•6Ucurrent font and always uses the INTL 0 and INTL 1 resources. This is not true. INTL °dONLNdÒ}µâ⁄(•”0 and 1°dONLNd˘âïÃ(±6]have been replaced by itl0 and itl1, and are not used except by applications that explicitly °dONLNdVâÃï⁄(±Íget°dONLNdZï°2(Ω6them °dONLNd_ï2°⁄)Xby doing a GetResource. There is a relevant Script Manager flag called IntlForce that is°dONLNd∏°≠Æ(…6Vcorrectly but incompletely explained in the Script Manager chapter. When IntlForce is °dONLNd°Æ≠⁄(…Ã
  3313. false, the°dONLNd≠πs(’6Lresources used by the International Utilities are determined by the current °dONLNde≠sπ⁄(’ëscript. The script that°dONLNd}π≈—(·6`is in use is determined by which font is in use for the port in use. For example, if you switch °dONLNd›π—≈⁄(·Ôto°dONLNd‡≈—»(Ì6\the Kyoto font, then you will be using the Japanese Script Interface System (KanjiTalk). If °dONLNd<≈»—⁄(ÌÊyou°dONLNd@—›Å(˘6do this with IntlForce °dONLNdW—Å›⁄)iJset to false, then you will use the resources that are associated with the°dONLNd¢›È∑(6!Japanese Script Interface System.°dONLNdƒı™*VWhen IntlForce is true, the International Utilities always use the resources that are °dONLNdı™⁄(»
  3314. associated°dONLNd%
  3315. §()6 with the system script; this is °dONLNdE§
  3316. ⁄)åAusually Roman. IntlForce is true by default. Actually, the Script°dONLNdá
  3317. u(56MManager initialization routine reads the itlc resource to determine what the °dONLNd‘
  3318. u⁄(5ìdefault is, and Apple°dONLNdÍ%T(A6Bplans to release the various international System files with this °dONLNd,T%⁄(Arfield set to true in the itlc°dONLNdJ%1}(M6Jresource. Applications that want to change the value of IntlForce can use °dONLNdî%}1⁄(Mõthe Script Manager°dONLNdß1=h(Y6call SetEnvirons °dONLNd∏1h=⁄)PNwith the smIntlForce verb. There is a Script Manager call, IntlScript, to find°dONLNd=I|(e6out the current value.°dONLNdam◊*$!Bug in System 4.1 version of itl1°dONLNd@yÖç*There is a bug in the itl1 °dONLNd[yçÖ⁄)uDresource in System 4.1. The itl1 resource contains arrays of day and°dONLNd†Öë8(≠6;month names, as did the INTL 1 resource. Their formats are:,
  3319. Courier
  3320.     °dONLNd‹ù®≥*days ARRAY [1..7] of STRING[15]°dONLNd¸ß≤Ω*
  3321. !months ARRAY[1..12] OF STRING[15]
  3322. °dONLNdΩ…B*8Every day and month is supposed to be coded as a Pascal °dONLNdVΩB…⁄(Â`string with a maximum of 15°dONLNdr…’Ω(Ò6%characters, and the actual length in °dONLNdó…Ω’⁄)•;the first byte of the string. In System 4.0 and System 4.1,°dONLNd”’·ö(˝6Tthe contents of each string is always a Pascal string of length 15, with the unused °dONLNd    '’ö·⁄(˝∏characters set°dONLNd    6·Ì‚(    6-to nulls. In other words, the length byte is °dONLNd    c·‚Ì⁄) 5set to hex 0F. This will be fixed in a future release°dONLNd    ôÌ˘Ç(6of the System file. If °dONLNd    ∞ÌǢ⁄)jEit is currently causing your application problems, you can change the°dONLNd    ˆ˘c(!6Blengths with ResEdit, or change them at run time, or use your own °dONLNd
  3323. 8˘c⁄(!Åitl1 resource and release°dONLNd
  3324. R∑(-6Syour application with an installer script. The recommended approach is to wait for °dONLNd
  3325. •∑⁄(-’a fixed°dONLNd
  3326. ≠Œ(96&version of the System file from Apple.°dONLNd
  3327. ‘AMÇ*0Further Reference: l4l˘°dONLNd
  3328. ÁN*Z.+
  3329. •°dONLNd
  3330. ÈN<Z¥)The International Utilities°dONLNd Z*f.(ÇH•°dONLNd Z<fô)The Script Manager ◊4◊˘
  3331. (Ï62) of 2)¸0Changes in International Utilities and Resourcesˇ≤◊#ˇ ˇˇˇˇ#◊†Ç 
  3332. /ZÅ#
  3333.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3334. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3335. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3336. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3337. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3338.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3339. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  3340. IR.°dONLNdn<Å(õZKeyboard Resource Q&As
  3341. °dONLNdÄ<èZ*Text°dONLNdÄdè˛(´ÇM.TX.KeybdRes.Q&As
  3342. °dONLNd0õ<ßt(√Z Revised by:°dONLNd<õÑߡ)HDeveloper Support Center°dONLNdUõæß˛(√‹ October 1992°dONLNdbß<≥q(œZ Written by:°dONLNdnßÑ≥ˇ)HDeveloper Support Center°dONLNdáßæ≥˛(œ‹ October 1990°dONLNdîø<À⁄(ÁZThis Technical Note contains a °dONLNd≥ø⁄À˛)û9collection of Q&As relating to a specific topic—questions°dONLNdÌÀ<◊†(ÛZGyou’ve sent the Developer Support Center (DSC) along with answers from °dONLNd4À†◊˛(Ûæthe DSC engineers.°dONLNdG◊<„u(ˇZ
  3343. While DSC °dONLNdQ◊u„˛)9Lengineers have checked the Q&A content for accuracy, the Q&A Technical Notes°dONLNdû„<Ôq( Z don’t have °dONLNd©„qÔ˛)5Qthe editing and organization of other Technical Notes. The Q&A function is to get°dONLNd˚Ô<˚Ÿ(Znew technical information and °dONLNdÔŸ˚˛)ù6updates to you quickly, saving the polish for when the°dONLNdP˚<(#Z,information migrates into reference manuals.°dONLNd}<k*:Q&As are now included with Technical Notes to make access °dONLNd∑k˛(;âto technical updates easier for°dONLNd◊<+.(GZ/you. If you have comments or suggestions about °dONLNd.+˛)Ú*Q&A content or distribution, please let us°dONLNd1+<7\(SZknow °dONLNd6+\7˛) Iby sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical°dONLNdÄ7<Ci(_Z9questions about Q&A content to DEVSUPPORT for resolution.°dONLNd∫O<[«*NNew Q&As and Q&As revised this month are marked with a bar in the side margin."n  ÜXÜ
  3344. °dONLNd    Ä<èå*4/ResEdit and Macintosh Portable 'KCAP' resources
  3345. °dONLNd9è<õb* Written:°dONLNdBèàõ¨)L6/17/91°dONLNdJõ<ßÅ(√ZLast reviewed:°dONLNdYõàߨ)L1/27/92°dONLNda≥<øe(€Z=I am trying to use the 'KCAP' resource to draw the Macintosh °dONLNdû≥eø˛(€ÉPortable keyboard layout in our°dONLNdæø<À≥(ÁZMapplication. I used the ResEdit to check 'KCAP' in both System 7 and the Key °dONLNd ø≥À˛(Á—Layout file, but°dONLNdÀ<◊ı(ÛZ(the Portable keyboard type is not there.°dONLNdE◊<„N* ___°dONLNdIÔ<˚*+The resource numbers 6 and 7 of 'KCAP' are °dONLNdtÔ˚˛)€-contained in the ROM of the Portable and some°dONLNd¢˚<∫(#ZMother Macintosh models. Being located in ROM, the resources are not directly °dONLNdÔ˚∫˛(#ÿ
  3346. viewable with°dONLNd˝<
  3347. (/Z(ResEdit. They do, however, exist in the °dONLNd%
  3348. ˛)Œ,resource chain, so a RGetResource for 'KCAP'°dONLNdR<√(;ZNnumber 6 should load and return a pointer to this resource. ROM resources and °dONLNd†√˛(;· the resource°dONLNd≠<+˘(GZZchain are discussed in the Resource Manager chapters of Inside Macintosh Volumes IV and V.
  3349. °dONLNdC<Rú*'0Using Macintosh KCAP resource to draw a keyboard
  3350. °dONLNd9R<^b* Written:°dONLNdBRà^¨)L1/10/92°dONLNdJ^<jÅ(ÜZLast reviewed:°dONLNdY^àj¶)L4/7/92°dONLNd`v<ÇL(ûZ5How can I use the KCAP resource to draw the keyboard?°dONLNdñÇ<éN* ___ ◊X◊
  3351. *BKeyboard Resource Q&As(Ï1) of 3ˇ°¿Ù%%DSIDICT:_cv
  3352. currentdict /bu known {bu}if
  3353. userdict /_cv known not{userdict /_cv 30 dict put}if
  3354. _cv begin
  3355. /bdf{bind def}bind def
  3356. currentscreen/cs exch def/ca exch def/cf exch def
  3357. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3358. /ss{//cf //ca //cs setscreen}bdf
  3359. /stg{ss setgray}bdf
  3360. /strgb{ss setrgbcolor}bdf
  3361. /stcmyk{ss cvcmyk}bdf
  3362. /min1{dup 0 eq{pop 1}if}bdf
  3363. end
  3364. currentdict /bn known {bn}if
  3365. †ø:◊#ˇ ˇˇˇˇ#◊ 
  3366. IR,Times
  3367. .+6-Macintosh Technical Notes /4/˘
  3368. °dONLNd)Œ*YKCAP resources describe the key layout of Macintosh keyboards. They are intended for use °dONLNdYŒ)⁄(EÏby°dONLNd\)5Ä(Q6the Key Caps desk °dONLNdn)Ä5⁄)h@accessory, but applications can also take advantage of KCAPs for°dONLNdØ5AÕ(]6$information about key arrangements. °dONLNd”5ÕA⁄)µ0The program kcapApp demonstrates use of the KCAP°dONLNdAM(i65resource and is available in the Snippets collection.°dONLNd:Ye⁄*(This is the format of the KCAP resource:°dONLNdcq}·*+  rect, boundary for the keyboard (8 bytes)°dONLNdè}â* :  rect, appropriate for an editable line of text (8 bytes)°dONLNd âï* 3  integer, number of key shapes to follow (2 bytes)°dONLNd°≠y*  for each key shape:°dONLNd≠πI* C    integer, number of points defining this key shape - 1 (2 bytes)°dONLNd[π≈h*     for each point:°dONLNdo≈—Ë* 0      point, opposite corner of a rect (2 bytes)°dONLNd†›ÈÍ*.    number of keys of this shape - 1 (2 bytes)°dONLNdœÈıa*     for each key:°dONLNd·ı±* "      byte, modifier mask (1 byte)°dONLNd
  3369. "* 9      byte, OR/AND setting for modifier mask (1 bit) plus°dONLNd>
  3370. ÷* -        virtual keycode for this key (7 bits)°dONLNdl%* :      integer, vertical offset from previous key (2 bytes)°dONLNdß%1%* <      integer, horizontal offset from previous key (2 bytes)°dONLNd‰=Iü*RThe keyboard boundary rect may be offset from the origin. It can be realigned with°dONLNd7Ua6*<    OffsetRect(keybdRect, - keybdRect.left, - keybdRect.top)°dONLNdtmy∞*SEach key shape consists of one or more rectangles. The rectangles are defined by a °dONLNd«m∞y⁄(   series of°dONLNd—yÖá(°6points, with one point °dONLNdËyáÖ⁄)oFspecifying each rectangle. The first point is the opposite corner of a°dONLNd/Öë(≠64rectangle anchored at the starting pen location for °dONLNdcÖë⁄)Í.the key; the next point is the opposite corner°dONLNdíëùN(π6Dof a rectangle from the last point; and so on. The key shape is the °dONLNd÷ëNù⁄(πlunion of the rects defined by°dONLNdÙù©J(≈6 the points.°dONLNdµ¡*.Note that a rectangle’s point may be above or °dONLNd.µ¡⁄)ÿ0to the left of the previous point. To QuickDraw,°dONLNd_¡Õ,(È6this °dONLNdd¡,Õ⁄)Zwould define an empty rectangle, so the rectangle’s horizontal and/or vertical coordinates°dONLNdøÕŸß(ı6Tmay need to be swapped before FrameRect is called to add a rect to the key’s region.°dONLNdÂÒo*The pen is moved °dONLNd%ÂoÒ⁄)WJto the top left of the keyboard boundary rect before drawing each group of°dONLNdpÒ˝H(6Akeys of a given shape. The pen location for each key is given as °dONLNd±ÒH˝⁄(f a horizontal and vertical offset°dONLNd“˝    ê(%6from the pen location for °dONLNdÏ˝ê    ⁄)xEthe previous key. The pen location for the first key of each shape is°dONLNd2    w(16Kan offset from the top left corner of the keyboard boundary rectangle. The °dONLNd}    w⁄(1ïpen does not change°dONLNdë!¶(=6location when a key is drawn.°dONLNdØ-9±*RUse KeyTrans to determine the character to be drawn on the key. The KCAP resource °dONLNd    -±9⁄(Uœprovides°dONLNd    
  3371. 9E£(a6Qa 7-bit virtual keycode, plus a mask for the modifiers to be passed to KeyTrans. °dONLNd    [9£E⁄(a¡ If the most°dONLNd    gEQs(m6Ksignificant bit of the keycode byte is set, AND the desired modifiers with °dONLNd    ≤EsQ⁄(mëthe modifier mask. If°dONLNd    »Q]˙(y61the bit is clear, OR the modifiers with the mask.°dONLNd    ˙iuO*CThe high bit of the virtual keycode byte indicates to KeyTrans the °dONLNd
  3372. =iOu⁄(ëmtype of the keystroke; before°dONLNd
  3373. [uÅ∫(ù6$calling KeyTrans, clear the bit for °dONLNd
  3374. u∫Å⁄)¢<a keydown, or set it for a keyup. The bit should be clear if°dONLNd
  3375. ºÅç÷(©6$you’re drawing a keyboard. KeyTrans °dONLNd
  3376. ‡Å÷ç⁄)æ4sets the state appropriately for dead keys only when°dONLNd çô|(µ6called for keydowns. ◊4◊˘
  3377. *72) of 3(ÏèKeyboard Resource Q&Asˇ“◊#ˇ ˇˇˇˇ#◊ 
  3378. IR,Times
  3379. .+Z-Developer Support Center(-Ê October 1992 /X/
  3380. °dONLNd<)æ(EZMThe global KbdType ($21E), a byte, contains the KCAP resource number for the °dONLNdMæ)˛(E‹
  3381. last keyboard°dONLNd[)<5m(QZ:used. Under System 6, KCAP resources are kept in the file °dONLNdï)m5˛(Qã“Key Layout” in the System°dONLNd∞5<A˘(]ZVfolder. Starting with System 7, KCAP resources are in the System file. Alternatively, °dONLNd5˘A˛(]a°dONLNdA<MÖ(iZ?machine’s KCAP may be stored in ROM, where it’s available with °dONLNdGAÖM˛(i£the GetResource call but°dONLNd`M<Y“(uZcannot be viewed with ResEdit.°dONLNde<q˙*%For more information on KeyTrans and °dONLNd§e˙q˛)æ0KCHRs, see Chapter 10 of Inside Macintosh Volume°dONLNd’q<}Ë(ôZ#V, pages 14-23 and 14-96 of Inside °dONLNd¯qË}˛)¨5Macintosh Volume VI, and the Macintosh Technical Note°dONLNd.}<âò(•ZC“Key Mapping.” KCAP resources are discussed on pages 14-95, 14-100 °dONLNdq}òâ˛(•∂and 14-101 of Inside°dONLNdÜâ<ï®(±ZMacintosh Volume VI.
  3382. °dONLNdõ≠<ºy*'-Macintosh Option key: Techniques for ignoring
  3383. °dONLNd…º<»b* Written:°dONLNd“ºà»≤)L10/16/91°dONLNd€»<‘Å(ZLast reviewed:°dONLNdÍ»à‘¨)L2/28/92°dONLNdÚ‡<Ïà(ZI would like to °dONLNd‡àÏ˛)LIuse the Macintosh Option key as the Control key for keyboards that lack a°dONLNdLÏ<¯d(ZControl °dONLNdTÏd¯˛)(Nkey, such as for Macintosh Plus keyboards. How can I find the ASCII value that°dONLNd£¯<À( ZSwould have been returned if the Option key weren’t pressed, in a way that would be °dONLNdˆ¯À˛( È
  3384. compatible°dONLNd<•(,Zwith other keyboards?°dONLNd<N* ___°dONLNd(<4*+There are a couple of clean ways to ignore °dONLNdF(4˛) 2the Option key. One is to “reprocess” the keyboard°dONLNdy4<@(\Z/event. The fourth byte of the event message is °dONLNd®4@˛)‹1the ASCII code, but the third byte is the virtual°dONLNd⁄@<Lœ(hZkey code. The system calls the °dONLNd˘@œL˛)ì<trap KeyTrans to map the virtual key code to ASCII according°dONLNd6L<X(tZ+to a 'KCHR' resource. You can do the same, °dONLNdaLX˛)Ÿ1and since the high byte of the modifiers are part°dONLNdìX<d˜(ÄZ(of the input to KeyTrans, you can strip °dONLNdªX˜d˛)ª6out the Option key, call KeyTrans on the third byte of°dONLNdÚd<p(åZ+the event message, and get back the “true” °dONLNddp˛) -ASCII keypress. KeyTrans and 'KCHR' resources°dONLNdKp<|U(òZ8are documented in Chapter 10 of Inside Macintosh Volume °dONLNdÉpU|˛(òs!V, Chapter 14 of Inside Macintosh°dONLNd•|<àÇ(§Z?Volume VI (pages 14-23 and 14-96), and the Macintosh Technical °dONLNd‰|Çà˛(§†Note “Key Mapping.” In°dONLNd˚à<î(∞Z.Pascal, these steps would look something like:,
  3385. Courier
  3386.     °dONLNd*†<´ï*E    keycode := BAND(event.message, keyCodeMask); { get virtual code }°dONLNdp™<µ@*
  3387. 4    keycode := BSR(keycode, 8); { move to low byte }°dONLNd•¥<øÊ*
  3388. "    { now combine with modifiers }°dONLNd»æ<…^*
  3389. :    keycode := BOR(keycode, BAND($FF00, event.modifiers));°dONLNd»<”Å*
  3390. A    keycode := BAND(keycode, $FFFF - optionKey); { strip option }°dONLNdF“<›@*
  3391. 4    newkey := KeyTrans(KCHRHandle^, keyCode, state);
  3392. °dONLNd{Ë<Ùé*The resource ID °dONLNdãËéÙ˛)RGof the current KCHR is available as GetScript(GetEnvirons(smKeyScript),°dONLNd”Ù<a(Z9smScriptKeys). Alternatively, a pointer to the KCHR data °dONLNd     Ùa˛(is available under System 7 as°dONLNd    +< fi((ZRGetEnvirons(smKCHRCache), as discussed in the Tech Note “International Canceling.”°dONLNd    ~<$T*This °dONLNd    ÉT$˛)Tmethod may work for you, but there is a possible problem: dead keys. Since dead keys°dONLNd    ÿ$<0”(LZYare processed before your application gets the event, your application will not see (for °dONLNd
  3393. 1$”0˛(LÒexample)°dONLNd
  3394. :0<<›(XZWthe first Option-e typed. However, the dead keys are specified in the 'KCHR' resource, °dONLNd
  3395. ë0›<˛(X˚so you°dONLNd
  3396. ò<<Hg(dZ>can create a KCHR (ResEdit 2.1.1 includes a template) to omit °dONLNd
  3397. ÷<gH˛(dÖdead keys (and, if you choose,°dONLNd
  3398. ıH<Tß(pZoption characters) and °dONLNd HßT˛)kIinclude it with your application. Call SetScript to get the system to use°dONLNd VT<`Ω(|ZIyour 'KCHR' (see the Tech Note “Key Mapping,” IM V-313, and IM VI 14-40).°dONLNd †l<x‚*RAnother problem is that System 7 ignores a 'KCHR' in the application’s resources, °dONLNd Úl‚x˛(îso an°dONLNd ¯x<ÑŸ(†ZSapplication’s 'KCHR' has to be installed in the system. You can install the 'KCHR' °dONLNd KxŸÑ˛(†˜with an°dONLNd SÑ<êH(¨Z8installer program, or provide a keyboard file users can °dONLNd ãÑHê˛(¨f%drag to the System file. (To create a°dONLNd ±ê<ú$(∏Z0keyboard file, use ResEdit to put the 'KCHR' in °dONLNd ·ê$ú˛)Ë.the System file, and then drag it out with the°dONLNd
  3399. ú<®í(ƒZSystem 7 Finder.) ◊X◊
  3400. *(Keyboard Resource Q&As(Ï3) of 3ˇ@◊#ˇ ˇˇˇˇ#◊†Ç 
  3401. /ZÅ#
  3402.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3403. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3404. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3405. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3406. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3407.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3408. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  3409. IR.°dONLNdz<çp(ßZ#Script Manager’s Pixel2Char Routine
  3410. °dONLNd$å<õZ*Text°dONLNd*åâõ˛(∑ßM.TE.Pixel2Char
  3411. °dONLNd:ß<≥t(œZ Revised by:°dONLNdFßÑ≥()HMark B. Johnson & Dave McGary°dONLNddß¡≥˛(œfl August 1989°dONLNdp≥<øq(€Z Written by:°dONLNd|≥Ñøª)H Sue Bartalo°dONLNdà≥Õø˛(€Π   June 1989°dONLNdíÃ<ÿfl(ÙZ"This Technical Note discusses the ,
  3412. Courier°dONLNd¥Àfl◊%)£
  3413. Pixel2Char°dONLNdæÃ%ÿÂ)F( routine provided by the Script Manager.°dONLNdÁÿ<‰œ(ZChanges since June 1989:°dONLNdˇÿœ‰å)ì)  Clarified information, corrected minor °dONLNd(ÿ剞)Ωerrors, and replaced the°dONLNdA‰<r( Z
  3414. illustration. X°dONLNdO
  3415. <R*&The °dONLNdS    Rä)leftSide°dONLNd[
  3416. ä√)8
  3417.  flag in the °dONLNdh    √    )9
  3418. Pixel2Char°dONLNdr
  3419.     I)F
  3420.  routine was °dONLNd
  3421. I˛)@$inappropriately named, and it should°dONLNd§<#ù(?Znow be called the °dONLNd∂ù"Í)a leadingEdge°dONLNd¡Í#˛)M4 flag.  The reason for this change is that the value°dONLNdˆ#</Ç(LZ
  3422. Pixel2Char°dONLNd$Ç0•)F8 returns indicates whether a mouse-down occurred on the °dONLNd8$•0˛(L√leading edge of a°dONLNdJ0<<A(XZ:character, which is not always the left side.  (In Arabic °dONLNdÑ0A<˙(X_%or Hebrew, both of which are right-to°dONLNd©0˙<˛)π-°dONLNd™<<Há(dZHleft scripts, the mouse-down occurs on the right side of the character.)°dONLNdÛT<`ø*RWith this change, the interfaces also change.  Following are both the old and new °dONLNdETø`˛(|›definitions in°dONLNdT`<l∑(àZPascal and C respectively:°dONLNdox<Ñç*Old Definition
  3423.     °dONLNd~ê<õ‡*TFUNCTION Pixel2Char(textBuf: Ptr;textLen: INTEGER;slop: INTEGER;pixelWidth: INTEGER;°dONLNd”ö<•;*
  3424. 3                   VAR leftSide: BOOLEAN): INTEGER;°dONLNdÆ<π¬*Npascal short Pixel2Char(Ptr textBuf,short textLen,short slop,short pixelWidth,°dONLNdV∏<√    *
  3425. )                       Boolean *leftSide)
  3426. °dONLNdÄŒ<⁄ì*New Definition
  3427.     °dONLNdèÊ<Ò‡*TFUNCTION Pixel2Char(textBuf: Ptr;textLen: INTEGER;slop: INTEGER;pixelWidth: INTEGER;°dONLNd‰<˚J*
  3428. 6                   VAR leadingEdge: BOOLEAN): INTEGER;°dONLNd<¬*Npascal short Pixel2Char(Ptr textBuf,short textLen,short slop,short pixelWidth,°dONLNdj<*
  3429. ,                       Boolean *leadingEdge)
  3430. °dONLNdó%<1ã*The value of the °dONLNd®$ã0ÿ)O leadingEdge°dONLNd≥%ÿ1˚)M     flag is °dONLNdº$˚0)#True°dONLNd¿%1$) if °dONLNdƒ%$1˛)
  3431. *a mouse-down occurs on the leading edge of°dONLNdÔ1<=Ë(YZ_the character in its direction (e.g., the left side for a left-to-right script (Roman) and the °dONLNdN1Ë=˛(Yright°dONLNdT=<I—(eZZside for a right-to-left one (Arabic or Hebrew)).  Figure 1 illustrates these differences.°dONLNdØU<a_*8This Note describes the way script systems should work; °dONLNdÁU_a˛(}}however, in some systems, the°dONLNdb<np(äZ
  3432. values of °dONLNdapmΩ)4 leadingEdge°dONLNdbΩnî)M) and character offset are undefined when °dONLNdCbîn©)◊the °dONLNdGa©mÔ)
  3433. pixelWidth°dONLNdQbÔn˛)F is°dONLNdUn<z‹(ñZ#outside the boundaries of the text.°dONLNdyÜ<íÿ*UYou define the start of a right-to-left line to be on the right and the end to be on °dONLNdŒÜÿí˛(ƈ    the left;°dONLNdÿí<ûä(∫ZMtherefore, it follows that the start of a left-to-right line is on the left, °dONLNd%íäû˛(∫®while the end is on the°dONLNd=ü<´¥(«Zright.  The values at the °dONLNdWü¥´Õ)xstart°dONLNd\üÕ´fl) of °dONLNd`üfl´4)a line should be °dONLNdqû4™W)UFalse°dONLNdvüW´o)# for °dONLNd{ûo™º) leadingEdge°dONLNdÜüº´˛)M
  3434.  and zero for ◊X◊
  3435. (ÏZ#Script Manager’s Pixel2Char Routine(Ï1) of 2ˇ°¿Ù%%DSIDICT:_cv
  3436. currentdict /bu known {bu}if
  3437. userdict /_cv known not{userdict /_cv 30 dict put}if
  3438. _cv begin
  3439. /bdf{bind def}bind def
  3440. currentscreen/cs exch def/ca exch def/cf exch def
  3441. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3442. /ss{//cf //ca //cs setscreen}bdf
  3443. /stg{ss setgray}bdf
  3444. /strgb{ss setrgbcolor}bdf
  3445. /stcmyk{ss cvcmyk}bdf
  3446. /min1{dup 0 eq{pop 1}if}bdf
  3447. end
  3448. currentdict /bn known {bn}if
  3449. †ø=$◊#ˇ ˇˇˇˇ#◊ 
  3450. IR,Times
  3451. .+6-Macintosh Technical Notes /4/˘
  3452. °dONLNd*´*!character offset.  The values at °dONLNd!´*Ω)ìthe °dONLNd%Ω*—)end°dONLNd(—*Á) are ,
  3453. Courier°dONLNd-Á))True°dONLNd1*) for °dONLNd6)f) leadingEdge°dONLNdAf*⁄)M and the character offset°dONLNd[*6Ê(R6+is the total byte count of that line.  You °dONLNdÜ*Ê6⁄)Œ/should check for these out-of-bounds conditions°dONLNd∂6BÉ(^6explicitly and perform °dONLNdÕ6ÉB⁄)kHthe appropriate actions.  This change will appear in the next version of°dONLNdBNΩ(j6!the Script Manager documentation.†Ç†å†å°ñ °öˇ¸ë
  3454. z<ãa
  3455. 3·3·°dONLNdˇˇ+"Character and Line Direction Equal†ó°ÿˇˇÄ°÷ˇˇÄ†◊°¥        
  3456. y6¨ `†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"`"r"Ñ"ñ"®"∫"Ã"fi""""&"8"J"\"n"Ä"í"§"∂"»"⁄"Ï"˛†ç°ÿˇˇÄ†ø†Ÿ†◊°ñ °öˇÍ
  3457. ¢‹Ú
  3458.     
  3459. H°dONLNdˇˇ+†Zb†ó°ñ °öˇÎ
  3460. ¢|ÙϰdONLNdˇˇ(‡†a°dONLNdˇˇ)( °dONLNdˇˇ)  †ó†å
  3461. y6¨"ò††°§Îqéò-ì-òì$éì-
  3462. "ì-Ú##˚##˚˚###Ñ
  3463. z7z7†£
  3464. y6¨Ñ
  3465. z7z7#Ú#˚#˚˚#†° ì$ìy†ç°ñ °öˇ˝S
  3466. õQ¶˙
  3467.     °dONLNdˇˇ(£R
  3468. Left-Right°dONLNdˇˇ)$ line direction (°dONLNdˇˇ)7
  3469. teSysJust = 0°dONLNdˇˇ)A)†ó°ñ °öˇ˝%
  3470. èQöû°dONLNdˇˇ(óR
  3471. Left-Right°dONLNdˇˇ)$
  3472.  style run†ó°ñ °öˇ¸*
  3473. „QÔ®
  3474. °dONLNdˇˇ(ÏRleadingEdge flag†ó°ñ °öˇ˝5
  3475. ÒQ˛æ°dONLNdˇˇ*Character Offset†ó†å†å
  3476. y6¨"ß≥††°§˝qù≥ß¡¢¡ß≥¢∏ù≥¢¡
  3477. "¢¡Ú##˚##˚˚###Ñ
  3478. z7z7†£
  3479. y6¨Ñ
  3480. z7z7#Ú#˚#˚˚#†°"¢∏†ç†å"߯††°§˝qù¯ß¢߯¢˝ù¯¢
  3481. "¢Ú##˚##˚˚###Ñ
  3482. z7z7†£
  3483. y6¨Ñ
  3484. z7z7#Ú#˚#˚˚#†°"¢˝Â†ç†ç"≠6°∂ Ä"Æ”4°∂#"≠ì6 „x„#†å"܆†°§qx%Ü xÜ Å%Ü x
  3485. " x˚##˚####Ú˚#Ñ
  3486. z7z7†£
  3487. y6¨Ñ
  3488. z7z7#˚#˚##Ú˚†°  , Å†ç°ñ °öˇ˝a
  3489. Q(
  3490.     °dONLNdˇˇ*+
  3491. Right-Left°dONLNdˇˇ)$ line direction (°dONLNdˇˇ)7teSysJust = $FFFF°dONLNdˇˇ)U)†ó°ñ °öˇ˝%
  3492. )Q4û°dONLNdˇˇ(1R Right-Left °dONLNdˇˇ)&    style run†ó°ñ °öˇ˝*
  3493. pR}©
  3494. °dONLNdˇˇ(ySleadingEdge flag†ó°ñ °öˇ˝5
  3495. ~Rãø°dONLNdˇˇ*Character Offset†ó†å†å
  3496. y6¨"*™††°§˝q*ú4™/ú*™/•4™/ú
  3497. "/ú˚##˚####Ú˚#Ñ
  3498. z7z7†£
  3499. y6¨Ñ
  3500. z7z7#˚#˚##Ú˚†°"/¿Â†ç†å"*Ô††°§˝q*·4Ô/·*Ô/Í4Ô/·
  3501. "/·˚##˚####Ú˚#Ñ
  3502. z7z7†£
  3503. y6¨Ñ
  3504. z7z7#˚#˚##Ú˚†°"/†ç†ç":6°∂ Ä";“6°∂#":í6 qwq"°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥"q솵°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"qì"wì"}ì"Éì"âì"èì†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥"s†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"s"y""Ö"ã†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥"Â°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"Âî"Îî"Òî"˜î"˝î"î†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥"ˆµ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"Ë"Ó"Ù"˙"†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°ñ °ö
  3505. s~ãã°dONLNdˇˇ(|ÅT
  3506. °dONLNdˇˇ+ 2†ó°ñ °ö
  3507. túå®°dONLNdˇˇ(}üF
  3508. °dONLNdˇˇ* 2†ó°ñ °ö
  3509. tªå»°dONLNdˇˇ(}æT
  3510. °dONLNdˇˇ+ 1†ó°ñ °ö
  3511. t‹å˰dONLNdˇˇ(}flF
  3512. °dONLNdˇˇ* 1†ó°ñ °ö
  3513. t˚å°dONLNdˇˇ(}˛T
  3514. °dONLNdˇˇ+ 0†ó°ñ °ö
  3515. sã$°dONLNdˇˇ(|F
  3516. °dONLNdˇˇ* 0†ó°ñ °ö
  3517. Á~ˇä°dONLNdˇˇ(ÅF
  3518. °dONLNdˇˇ* 0†ó°ñ °ö
  3519. Áùˇ™°dONLNdˇˇ(†T
  3520. °dONLNdˇˇ+ 0†ó°ñ °ö
  3521. Áºˇ»°dONLNdˇˇ(øF
  3522. °dONLNdˇˇ* 1†ó°ñ °ö
  3523. ÁfiˇÎ°dONLNdˇˇ(·T
  3524. °dONLNdˇˇ+ 1†ó°ñ °ö
  3525. Á¸ˇ°dONLNdˇˇ(ˇF
  3526. °dONLNdˇˇ* 2†ó°ñ °ö
  3527. Áˇ&°dONLNdˇˇ(T
  3528. °dONLNdˇˇ+ 2†ó†å°ñ °öˇÍ
  3529. 0úÄΔ
  3530. H°dONLNdˇˇ(nùb†ó°ñ °öˇÏ
  3531. 0±Ñ0°dONLNdˇˇ)?a°dONLNdˇˇ)(   †ó†ç°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥
  3532. y6¨"„‘!†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"„‘"È‘"Ô‘"ı‘"˚‘"‘†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥"s“†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"s“"y“"“"Ö“"ã“"듆ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂ Ä°ÿˇˇÄ°÷ˇˇÄ†◊°¥"¨≥V†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"¨≥"≤≥"∏≥"æ≥"ƒ≥" ≥"–≥"÷≥"‹≥"‚≥"Ë≥"Ó≥"Ù≥"˙≥"≥†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂ Ä°ÿˇˇÄ°÷ˇˇÄ†◊°¥"≠ÛW†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"≠Û"≥Û"πÛ"øÛ"≈Û"ÀÛ"—Û"◊Û"›Ù"„Ù"ÈÙ"ÔÙ"ıÙ"˚Ù"Ù†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂ Ä°ÿˇˇÄ°÷ˇˇÄ†◊°¥"9≤W†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"9≤"?≤"E≤"K≤"Q≤"W≤"]≤"c≤"i≤"o≤"u≤"{≤"Å≤"á≤"ç≤†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂ Ä°ÿˇˇÄ°÷ˇˇÄ†◊°¥":ÒV†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å":Ò"@Ò"FÒ"LÒ"RÒ"XÒ"^Ò"dÒ"jÒ"pÒ"vÒ"|Ò"ÇÒ"àÒ"éÒ†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#†ç†å°ñ °öˇ¸ê
  3533. ú7≠Z
  3534. °dONLNdˇˇ(®8$Character and Line Direction Unequal†ó°ñ °ö
  3535.  $%
  3536. °dONLNdˇˇ+„mT
  3537. °dONLNdˇˇ+ 2†ó°ñ °ö
  3538.  ¸$    °dONLNdˇˇ(ˇT
  3539. °dONLNdˇˇ+ 0†ó°ñ °ö
  3540.  ‹$˰dONLNdˇˇ(flF
  3541. °dONLNdˇˇ* 1†ó°ñ °ö
  3542.  ú$®°dONLNdˇˇ(üF
  3543. °dONLNdˇˇ* 2†ó°ñ °ö
  3544.  ~$ä°dONLNdˇˇ(ÅF
  3545. °dONLNdˇˇ* 0†ó†å°ñ °öˇÍ
  3546. »öƒ
  3547. H°dONLNdˇˇ(õb†ó°ñ °öˇÏ
  3548. »Ø.°dONLNdˇˇ)?a°dONLNdˇˇ)(   †ó†ç°ÿˇˇÄ°÷ˇˇÄ†◊°¥        
  3549. y6¨ 7_7†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"6_"6q"6É"6ï"6ß"6π"6À"6›"6Ô"6"6"6%"67"6I"6["6m"6"6ë"6£"6µ"6«"6Ÿ"6Î"6˝†ç°ÿˇˇÄ†ø†Ÿ†◊†å"Ω††°§ˇq≥Ω+∏+Ω∏"≥∏+
  3550. "∏+Ú##˚##˚˚###Ñ
  3551. z7z7†£
  3552. y6¨Ñ
  3553. z7z7#Ú#˚#˚˚#†° ∏"∏w†ç°ñ °öˇ˝U
  3554. ≥Qæ˛
  3555.     °dONLNdˇˇ(ªR
  3556. Left-Right°dONLNdˇˇ)$ line direction (°dONLNdˇˇ)7teSysJust = 0)†ó°ñ °öˇ˝%
  3557. ¡QÃû°dONLNdˇˇ(…R
  3558. Right-Left°dONLNdˇˇ)$
  3559.  style run†ó°ñ °öˇ˝*
  3560. 
  3561. R©
  3562. °dONLNdˇˇ(SleadingEdge flag†ó°ñ °öˇ˝3
  3563. R&ª°dONLNdˇˇ*Character Offset†ó†å
  3564. y6¨"¬™††°§˝q¬úÙ«ú¬™«•Ù«ú
  3565. "«ú˚##˚####Ú˚#Ñ
  3566. z7z7†£
  3567. y6¨Ñ
  3568. z7z7#˚#˚##Ú˚†°"«¿Â†ç†å"¬Ô††°§˝q¬·ÃÔ«·¬Ô«ÍÃÔ«·
  3569. "«·˚##˚####Ú˚#Ñ
  3570. z7z7†£
  3571. y6¨Ñ
  3572. z7z7#˚#˚##Ú˚†°"«†ç"“6°∂ Ä"“”7°∂#"“í6     w    "°ñ °ö
  3573.  º$…°dONLNdˇˇ(øT
  3574. °dONLNdˇˇ+ 1†ó°ñ °ö
  3575. ì˙´°dONLNdˇˇ+={F
  3576. °dONLNdˇˇ* 2†ó°ñ °ö
  3577. ìö´ß°dONLNdˇˇ(úùT
  3578. °dONLNdˇˇ+ 0†ó°ñ °ö
  3579. ì´å°dONLNdˇˇ(úÇT
  3580. °dONLNdˇˇ+ 2†ó†å°ñ °öˇÍ
  3581. N⁄û    
  3582. H°dONLNdˇˇ(å€b†ó°ñ °öˇÎ
  3583. Nz†Í°dONLNdˇˇ(åûa°dONLNdˇˇ)( °dONLNdˇˇ)  †ó†ç†å
  3584. y6¨":Ö††°§Îq:wDÖ?w:Ö?ÄDÖ?w
  3585. "?w˚##˚####Ú˚#Ñ
  3586. z7z7†£
  3587. y6¨Ñ
  3588. z7z7#˚#˚##Ú˚†° ?+?Ćç°ñ °öˇ˝]
  3589. <QG
  3590.     °dONLNdˇˇ(DR
  3591. Right-Left°dONLNdˇˇ)$ line direction (°dONLNdˇˇ)7teSysJust = $FFFF°dONLNdˇˇ)U)†ó°ñ °öˇ˝%
  3592. IQTû°dONLNdˇˇ(QR Left-Right °dONLNdˇˇ)&    style run†ó°ñ °öˇ˝*
  3593. èQú®
  3594. °dONLNdˇˇ(òRleadingEdge flag†ó°ñ °öˇ˝>
  3595. ùQ™–°dONLNdˇˇ*Character Offset†ó†å
  3596. y6¨"S±††°§˝qI±SøNøS±N∂I±Nø
  3597. "NøÚ##˚##˚˚###Ñ
  3598. z7z7†£
  3599. y6¨Ñ
  3600. z7z7#Ú#˚#˚˚#†°"N∂†ç†å"Sˆ††°§˝qIˆSNSˆN˚IˆN
  3601. "NÚ##˚##˚˚###Ñ
  3602. z7z7†£
  3603. y6¨Ñ
  3604. z7z7#Ú#˚#˚˚#†°"N˚†ç"Y6°∂ Ä"Z—5°∂#"Yë6 êvê!°ñ °ö
  3605. ì∫´Δ°dONLNdˇˇ(úΩF
  3606. °dONLNdˇˇ* 1†ó°ñ °ö
  3607. 쀴˰dONLNdˇˇ(úfiT
  3608. °dONLNdˇˇ+ 1†ó°ñ °ö
  3609. ì´"°dONLNdˇˇ(úF
  3610. °dONLNdˇˇ* 0†ó°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥
  3611. y6¨"ï—†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"ï—"õ—"°—†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥"솵°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"ì"ì"ì"$ì"*ì†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥"†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å""""%"+†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥"”†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"”"”" ”"&”",”†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂ Ä°ÿˇˇÄ°÷ˇˇÄ†◊°¥"_ÚˇG†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"_Ú"eÚ"kÚ"qÚ"wÚ"}Ú"ÉÒ"âÒ"èÒ"ïÒ"õÒ"°Ò†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂ Ä°ÿˇˇÄ°÷ˇˇÄ†◊°¥"⁄≤V†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"⁄≤"‡≤"Ê≤"Ï≤"Ú≤"¯≤"˛≤"≤"
  3612. ≤"≤"≤"≤""≤"(≤".≤†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂ Ä°ÿˇˇÄ°÷ˇˇÄ†◊°¥"€ÒW†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"€Ò"·Ò"ÁÒ"ÌÒ"ÛÒ"˘Ò"ˇÒ"Ò" Ò"Ò"Ò"Ò"#Ò")Ò"/Ò†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥"ï통°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"ïí"õí"°í†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂@İÿˇˇÄ°÷ˇˇÄ†◊°¥"°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"î"ö"††ç°ÿˇˇÄ†ø†Ÿ†◊°∂#°∂ Ä°ÿˇˇÄ°÷ˇˇÄ†◊°¥"b±ˇG†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿ†å"b±"h±"n±"t±"z±"ı"Ü∞"å∞"í∞"ò∞"û∞"§∞†ç°ÿˇˇÄ†ø†Ÿ†◊°∂#†ç†ç°∂ Ä°∂#°∂ Ä°∂#°∂@İ∂#°∂@İ∂#°∂@İ∂#°∂@İ∂#°∂@İ∂#°∂@İ∂#°∂ Ä°∂#°∂ Ä°∂#°∂ Ä°∂#°∂ Ä°∂#°∂ Ä°∂#°∂ Ä°∂#°∂@İ∂#°∂@İ∂#°∂@İ∂#°∂@İ∂#°∂ Ä°∂#°∂ Ä°∂#°∂ Ä°∂#°∂@İ∂#°∂@İ∂#°∂ Ä°∂#†É
  3613. IR°dONLNd8ôã•g(¡©$Figure 1–Pixel2Char leadingEdge Flag ◊4◊˘
  3614. (Ï62) of 2(Ïa#Script Manager’s Pixel2Char Routineˇî◊#ˇ ˇˇˇˇ#◊†Ç 
  3615. /ZÅ#
  3616.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3617. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3618. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3619. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3620. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3621.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3622. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  3623. IR.°dONLNdz<ç„(ßZ1Accessing the Script Manager Print Action Routine
  3624. °dONLNd2å<õZ*Text°dONLNd8åÖõ˛(∑£M.TE.PrintAction
  3625. °dONLNdIß<≥t(œZ Revised by:°dONLNdVß≈≥˛(œ„
  3626. March 1988°dONLNda≥<øq(€Z Written by:°dONLNdm≥Ñøª)H
  3627. Mark Davis°dONLNdx≥±ø˛(€œ
  3628. November 1987°dONLNdÜÀ<◊ö(ÛZThis technical note °dONLNdöÀö◊˛)^Fdescribes how Print Drivers can access the Script Manager Print Action°dONLNd·◊<„k(ˇZAroutine to print unconventional text, such as Japanese or Arabic. X
  3629. °dONLNd#<ö*4
  3630. General Notes
  3631. °dONLNd1#</∑*Scripts such as Japanese °dONLNdJ#∑/˛){?or Arabic modify the normal QuickDraw text handling in order to°dONLNdä0<<p(XZ
  3632. represent °dONLNdî0p<≤)47text properly. On the screen, this is done by trapping ,
  3633. Courier°dONLNdÀ/≤;„(X–StdText°dONLNd“0„<˛)1 and°dONLNd◊<<Hó(eZ
  3634. StdTxtMeasure°dONLNd‰=óI¥)[, and °dONLNdÍ=¥I˛)Atransforming the text before printing. For example, for Hebrew or°dONLNd,I<UÔ(qZ`Arabic the text might be reversed, since text normally goes from right to left in those scripts.°dONLNdça<ml*CPrint drivers require slightly different handling, for two reasons:°dONLNd—y<Öπ*1. A print driver might °dONLNdÈyπÖ˛)}<not call the standard QuickDraw procedures. For example, the°dONLNd&Ö<ë"(≠Z2LaserWriter writes directly in PostScript instead.°dONLNdYù<©Ω*S2. A print driver might need to format the text, for accurate line-layout. In this °dONLNd¨ùΩ©˛(≈€case, the text°dONLNdª©<µË(—Z#needs to be transformed before the °dONLNdfi©Ëµ˛)¨:driver performs line-layout. If the driver is spooling the°dONLNdµ<¡P(›Z>text, and will replay the text a second time, the text cannot °dONLNdWµP¡˛(›n#be transformed a second time, since°dONLNd{¡<Õ–(ÈZthat would ruin the appearance.°dONLNdõŸ<ÂQ*For °dONLNdüŸQ²)Sexample, the ImageWriter driver calls QuickDraw procedures twice, once to spool and°dONLNdÛÂ<ÒÚ(
  3635. Z&once to unwind the spooling. The text °dONLNdÂÚÒ˛)∂6must be transformed when spooling, so that line layout°dONLNdPÒ<˝Œ(ZRcan be done, but when unwinding, the transformation must be turned off completely.°dONLNd£    <z*?Note that some drivers, such as the LaserWriter, use QuickDraw °dONLNd‚    z˛(1òre-entrantly: the application°dONLNd<"ã(>ZEprogram calls a QuickDraw routine, which is directed to the driver’s °dONLNdEã! (>©    grafProcs°dONLNdN "˛)?
  3636. , which in°dONLNdY"<.(JZ)turn call QuickDraw internally to put up °dONLNdÇ".˛)Ã/status messages on the screen. The Print Action°dONLNd≤.<:n(VZ
  3637. procedure °dONLNdº.n:˙)2Thandles the text properly so that the text transformations are enabled during the re°dONLNd.˙:˛(V-°dONLNd:<F{(bZFentrant calls, so that the status messages will be properly formatted.
  3638. °dONLNdX^<mA*'%When To Call the Print Action Routine
  3639. °dONLNd~y<Öæ*The Script Manager Print °dONLNdóyæÖ˛)Ç?Action routine allows the print driver to be independent of the°dONLNd◊Ö<ëÿ(≠ZXparticular scripts being used. The printing driver should call this routine whenever it °dONLNd/Öÿë˛(≠ˆchanges°dONLNd7í<ûO(∫Zthe °dONLNd;ëOùé)    grafProcs°dONLNdDíéûfi)? in the printing °dONLNdUëfiù)PgrafPort°dONLNd]íû6)8. The °dONLNdcí6û˛) )Print Action routine will then substitute°dONLNdçû<™{(«Z    grafProcs°dONLNdñü{´Œ)? of its own in the °dONLNd©ûŒ™
  3640. )S    grafProcs°dONLNd≤ü
  3641. ´Â)?/ record, saving the original routine addresses. ◊X◊
  3642. (ÏZ1Accessing the Script Manager Print Action Routine(Ï1) of 3ˇ°¿Ù%%DSIDICT:_cv
  3643. currentdict /bu known {bu}if
  3644. userdict /_cv known not{userdict /_cv 30 dict put}if
  3645. _cv begin
  3646. /bdf{bind def}bind def
  3647. currentscreen/cs exch def/ca exch def/cf exch def
  3648. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3649. /ss{//cf //ca //cs setscreen}bdf
  3650. /stg{ss setgray}bdf
  3651. /strgb{ss setrgbcolor}bdf
  3652. /stcmyk{ss cvcmyk}bdf
  3653. /min1{dup 0 eq{pop 1}if}bdf
  3654. end
  3655. currentdict /bn known {bn}if
  3656. †øt◊#ˇ ˇˇˇˇ#◊ 
  3657. IR,Times
  3658. .+6-Macintosh Technical Notes /4/˘
  3659. °dONLNd)5“*$_The Print Action routine will actually call a Print Action routine for each script system that °dONLNd_)“5⁄(Qis°dONLNdb5A»(]6(currently installed. Each of the script °dONLNdä5»A⁄)∞;Print Action routines will do the appropriate tasks for its°dONLNdΔAM=(i6system.
  3660. °dONLNdŒetÒ*' Calling the Print Action Routine
  3661. °dONLNdÔÄåq*KTo call the Print Action routine, the driver should use the following code:,
  3662. Courier
  3663.     °dONLNd;ò£O* intlGlobals°dONLNdGò`£o)Hequ°dONLNdKòÑ£ò)$$ba0°dONLNdPò®£)$; international globals°dONLNdh¢≠^(…6printActionOff°dONLNdw¢Ñ≠ì)lequ°dONLNd{¢®≠∑)$$16°dONLNd¢Ã≠l)$ ; offset to PrintAction proc ptr°dONLNd¢∂¡≥(›6; get procedure pointer to call°dONLNd≈ <’U+$tst.w°dONLNdÀ `’y)$Rom85°dONLNd‘ ’Å)ê; on a Macintosh + or better?°dONLNdÛ‘<flU(˚Zblt.s°dONLNd˘‘`fl∞)$@PrintActionDone°dONLNd ‘fl")ê
  3664. ; no, skip°dONLNdfi<ÈZ(Zmove.l°dONLNdfi`ȶ)$intlGlobals,d2°dONLNd.fiÈw)ê get international globals°dONLNdKË<ÛU(Zble.s°dONLNdQË`Û∞)$@PrintActionDone°dONLNdcËÛE)ê; not there, skip°dONLNdvÚ<˝Z(Zmove.l°dONLNd}Ú`˝y)$d2,a0°dONLNdÜÚ˝Y)ê; in address register°dONLNdù¸<Z(#Zmove.l°dONLNd§¸`…)$printActionOff(a0),d2°dONLNd∫¸r)ê; get print action address°dONLNd÷<U(-Zbeq.s°dONLNd‹`∞)$@PrintActionDone°dONLNdÓE)ê; not there, skip°dONLNd<Z(7Zmove.l°dONLNd`y)$d2,a0°dONLNdY)ê; in address register°dONLNd)$/ö(K6; set up arguments to call°dONLNdG8<CZ+$move.l°dONLNdN8`Có)$ <myPort>,d0°dONLNd\8C;)ê; pass the port°dONLNdmB<MZ(iZmove.w°dONLNdtB`Mó)$ <myVerb>,d1°dONLNdÇBM;)ê; pass the verb°dONLNdìL<WK(sZjsr°dONLNdóL`Wt)$(a0)°dONLNdüLWT)ê; call the procedure°dONLNd¥Vah(}6@PrintActionDone
  3665. °dONLNd≈xáœ*&Print Action Routine Verbs
  3666. °dONLNd‡ìüM*DThere are currently three verbs to pass to the Print Action routine.
  3667.     °dONLNd&´<∂x+$ paUnwindText°dONLNd4´®∂∑)lequ°dONLNd8´Ã∂÷)$–1°dONLNd<µ<¿s(‹Z paSpoolText°dONLNdIµ®¿∑)lequ°dONLNdMµÃ¿—)$1°dONLNdPø< }(ÊZ
  3668. paNoQuickDraw°dONLNd_ø® ∑)lequ°dONLNdcøÃ —)$3
  3669. °dONLNde÷‚C(˛6Use the °dONLNdm’C·{)+paUnwind°dONLNdu÷{‚ç)88 verb to ensure that the text is not transformed before °dONLNd≠÷ç‚©(˛´your °dONLNd≤’©·⁄)StdText°dONLNd∫‚Óç(
  3670. 6Mprocedure receives the text. This verb is used when playing back stored text °dONLNd‚çÓ⁄(
  3671. ´that has already°dONLNdÓ˙n(6been transformed.°dONLNd*~*The other two verbs (°dONLNd?~Ÿ)f
  3672. paNoQuickDraw°dONLNdLŸ‹)[ °dONLNdM‹Ò)and °dONLNdQÒ>) paSpoolText°dONLNd\>⁄)M") are used to ensure that the text°dONLNd ô(<6is transformed before your °dONLNdöô )ÅStdText°dONLNd°  9)1 procedure receives the °dONLNdπ9 h)o
  3673. text. The °dONLNd√hµ)/ paSpoolText°dONLNdŒµ ⁄)M verb is°dONLNd◊!-N(I6
  3674. used when °dONLNd·!N-à)6Ayour driver will use QuickDraw to image the text in the printing °dONLNd" à,¿(I¶grafPort°dONLNd*!¿-⁄)8. The°dONLNd0-9s(V6
  3675. paNoQuickDraw°dONLNd=.s:∂)[ verb is used °dONLNdK.∂:⁄)C:when the text is not drawn into the printing port by going°dONLNdÜ:F(b62through QuickDraw (e.g. the LaserWriter). In that °dONLNd∏:F⁄))case some languages (e.g. Japanese) which°dONLNd‚GSL(o6Duse an extended font structure may need to recast the text calls as °dONLNd&FLRÑ(ojCopyBits°dONLNd.GÑS†)8 calls.°dONLNd6_kÖ(á6IAs mentioned above, some applications may call QuickDraw from within the °dONLNd_Ök⁄(á£driver, as when a°dONLNdëlx·(î6%status window is updated. During any °dONLNd∂k·w<)…
  3676. StdTxtMeasure°dONLNd√l<xB)[ °dONLNdƒlBx⁄)calls in the driver during the°dONLNd„yÖv(°6application’s call to °dONLNd˘xvÑß)^StdText°dONLNdyßÖ    )1, the port is checked °dONLNdy    Ö⁄)b-against the printer port. If they match, then°dONLNdDÖë>(≠6@the text is not transformed. Otherwise, the text is transformed. ◊4◊˘
  3677. *?2) of 3)Ó1Accessing the Script Manager Print Action Routineˇú◊#ˇ ˇˇˇˇ#◊ 
  3678. IR,Times
  3679. .+Z-Developer Support Center(-Ï
  3680. March 1988 /X/
  3681. °dONLNd<)™(EZOThe solutions adopted by the Print Action routine assume that the print driver °dONLNdO™)˛(E»does not measure°dONLNd`*<6Â(RZ$or draw text except within calls to ,
  3682. Courier°dONLNdÑ)Â5@)©
  3683. StdTxtMeasure°dONLNdë*@6R)[ or °dONLNdï)R5É)StdText°dONLNdú*É6±)1
  3684. . If your °dONLNd¶*±6˛).driver does text°dONLNd∑6<B–(^ZUbuffering (as for line layout), make sure that any measurements are performed within °dONLNd 6–B˛(^Ó    these two°dONLNdB<N†(jZcalls. For example, °dONLNd*B†N˛)dByou might buffer both the text and its screen width as measured by°dONLNdmN<Zv(vZ
  3685. QuickDraw.°dONLNdx~<ä¶*0Further Reference: ©X©°dONLNdããNóR+
  3686. •°dONLNdçã`óΩ)The Script Manager ◊X◊
  3687. (ÏZ1Accessing the Script Manager Print Action Routine(Ï3) of 3ˇÜ◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  3688. /ZÅ#
  3689.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3690. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3691. .WIQkWIQk+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3692. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3693. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3694.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3695. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  3696. IR.°dONLNd{<éî(®Z
  3697. Safe cdevs
  3698. °dONLNd ç<úZ*Text°dONLNdççú˛(∏´
  3699. M.TE.SafeCDEV
  3700. °dONLNd®<¥q(–Z Written by:°dONLNd+®Ñ¥¡)H John Harvey°dONLNd7®¡¥˛(–fl August 1989°dONLNdC¿<Ã{(ËZ?This Technical Note describes a potential problem with Control °dONLNdÇ¿{Ã˛(ËôPanel devices (cdevs) that°dONLNdùÕ<Ÿa(ıZcontain ,
  3701. Courier°dONLNd•Ãaÿô)%EditText°dONLNd≠ÕôŸI)8' fields and presents a way to avoid it. X°dONLNd’Ú<˛À(ZThe Control Panel chapter in °dONLNdÚÚÀ˛)èInside Macintosh°dONLNdÚ˛å)R, Volume 5 describes, °dONLNdÚ垞)oin detail, how run-time°dONLNd0˛<
  3702. n(&Z?errors are handled by the Control Panel and a cdev.  There is, °dONLNdo˛n
  3703. ˛(&åhowever, a potential problem°dONLNdå <´(3Zwith cdevs that contain °dONLNd§
  3704. ´„)oEditText°dONLNd¨ „ò)8( items that this chapter does not cover.°dONLNd’$<0@(LZ7When a cdev is called by the Control Panel, the cdev’s °dONLNd #@/j(L^'DITL'°dONLNd$j0£)*
  3705.  resource is °dONLNd$£0˛)9concatenated to the°dONLNd31<=â(YZControl Panel’s °dONLNdC0â<≥)M'DITL'°dONLNdI1≥=¡)*9.  The Control Panel then lets the Dialog Manager update °dONLNdÇ1¡=˛(Yfl the window.°dONLNdè><JX(fZIf the °dONLNdñ>XJÍ)cdev contains an item of type °dONLNd¥=ÍI")íEditText°dONLNdº>"J˛)8., the Dialog Manager allocates and activates a°dONLNdÎJ<Vt(sZTEHandle°dONLNdÛKtWÄ)8: to be used for displaying and editing text.  All of this °dONLNd-KÄW˛(sûaction happens before the°dONLNdGX<d|(ÄZcdev gets the °dONLNdUW|c≠)@initDev°dONLNd\X≠dK)1  message from the Control Panel.°dONLNd}p<|U(òZ=As detailed in The Control Panel chapter, if an error occurs °dONLNd∫pU|˛(òs!from which a cdev cannot recover,°dONLNd‹}<â2(•Z2the cdev should dispose of any private memory and °dONLNd}2âÈ)ˆ'return the appropriate error code or a °dONLNd5|Èà˛)∑NIL°dONLNd9â<ïΔ(±Zvalue to the Control Panel.  °dONLNdVâΔï˛)ä>The Control Panel then grays out the cdev’s area, displays the°dONLNdïñ<¢î(æZLappropriate error dialog, and then deletes the items that were added to its °dONLNd·ïî°æ(æ≤'DITL'°dONLNdÁñ梬)*.°dONLNdÈØ<ªÿ(◊Z%All of this is fine, except that the °dONLNdÆÿ∫)úTEHandle°dONLNdت©)8  does not get deallocated.  The °dONLNd6Æ©∫·)ôEditText°dONLNd>Ø·ª˛)8 items°dONLNdEª<«k(„ZAget thrown away, including the strings in the item list that the °dONLNdܪk«˛(„âDialog Manager would use to°dONLNd¢»<‘∫(Zstore text entered into the °dONLNdæ«∫”Ú)~EditText°dONLNdΔ»Ú‘8)8 field, but the °dONLNd÷«8”p)FTEHandle°dONLNdfi»p‘ê)8 stays °dONLNdÂ»ê‘˛) there and stays active.°dONLNd˛‘<‡(¸Z/Figure 1 illustrates what this would look like. ◊X◊
  3706. *
  3707. Safe cdevs(Ï1) of 2ˇ°¿Ù%%DSIDICT:_cv
  3708. currentdict /bu known {bu}if
  3709. userdict /_cv known not{userdict /_cv 30 dict put}if
  3710. _cv begin
  3711. /bdf{bind def}bind def
  3712. currentscreen/cs exch def/ca exch def/cf exch def
  3713. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3714. /ss{//cf //ca //cs setscreen}bdf
  3715. /stg{ss setgray}bdf
  3716. /strgb{ss setrgbcolor}bdf
  3717. /stcmyk{ss cvcmyk}bdf
  3718. /min1{dup 0 eq{pop 1}if}bdf
  3719. end
  3720. currentdict /bn known {bn}if
  3721. †øË◊#ˇ ˇˇˇˇ#◊ 
  3722. IR,Times
  3723. .+6-Macintosh Technical Notes /4/˘†Ç†å
  3724. <V˛ÿ
  3725. 4wY˙õò*J|ŒƒJŒ¬wY˚ú⁄ˇ¸ê⁄
  3726. ô–⁄
  3727. ôp⁄
  3728. ôÔ˛ˆˇ¿ˆÙˇÏêı
  3729. <0¿Û
  3730. ôˈˇ ¿b0`ÙˇÔˇı
  3731. `<|y≥Δc«√ΔÛ Ëˆˇ¿`ff1Δfd˛fÙˇÏpı
  3732. `ff1Üf√ÊffÛfóˈˇ ¿`ff1ÜffgÊÙˇÓfpı
  3733. `ff1ÜfffÛ
  3734. ôˈˇ ¿bff1Üfff&ÙˇÏpı
  3735. <<fÉΔÊcΔÛ3˜Ô˛ˆˇ¿ˆÙˇÏÃ⁄ ⁄ 0⁄3Ÿˇ3⁄ˇ˝ô
  3736. ˘Â
  3737. ˘Â@\
  3738. ÿ˘(ÂT
  3739. ¯˘DÂ
  3740. ˘ÇÂ
  3741. ˘    Â@\
  3742. 8˘
  3743. òÂ
  3744. x˘É‹Â
  3745. ˘Ç ˇˇÇÂ@\ òÇ ˛Âà ˇà ¯ÄHÂ@_w x™®Hˇ¯Â ÄHˇ¸Â ™ÄH 8¡ ¯ÄH 8Â@]/ ®H 8 ¯ÄH <¡ ò®H 8Âf xÄH 8Â@]ô ™H 8 ¯ÄH <Âà ¯ÄH 8Âà ¯ˇà 8Â@\  8 ÿ <Âà x 8Â3 x 8Â@]ô àˇ¯Â òàúÂô ÿ
  3746. "8Âô ¯àòÂ@\ 
  3747. "8 òˇˇàúÂô 8
  3748. "8Â xàòÂ@]ô 
  3749. "8 xˇˇàúÂf
  3750. ò˘
  3751. "8Âf
  3752. ¯˘àòÂ@\
  3753. ˘
  3754. "8Âx8˛¿àúÂfD˛@
  3755. "8¡ x@Œ2Ã@àòÂ@]ô M)K@
  3756. "8Â 8EÈz@àúÂ3 xE    B@
  3757. "8Â3 ¯8…2@àòÂ@\
  3758. ˘
  3759. "8Â
  3760. 8˘àúÂ
  3761. ¯˘
  3762. "8ÂÃ
  3763. x˘àòÂ@]ô
  3764. ˘
  3765. "8Â
  3766. ˘àúÂ
  3767. 8˘
  3768. "8Â
  3769. ¯˘àòÂ@\
  3770. ˘
  3771. "8ÂX˘àú$Ëÿ˘
  3772. "8 ËU˘àò@@`Ë@\˘
  3773. "8 Ë˘àú$˪∏˘
  3774. "8 ËDX˘àò@@`Ë@\˘
  3775. "8 Ëx˘àú$Ëô˛
  3776. ˇÄ
  3777. "8 Ë¯˛
  3778. ``àò@@`Ë@_ˇò˛
  3779. Ä
  3780. "8 Ëf¯àú$ËŃ
  3781. "8 Ë¯
  3782. Ç$àò@@`Ë@_ˇÇ"
  3783. "8 Ëˇ x"àúÂô ¡
  3784. "8Â ÿàòÂ@\Ã xÄ
  3785. "8Â3 ¯&¡¯àú $CÑ
  3786. "8Â ÿF√|àòÂ@]ô ¯CÅ    Ä
  3787. "8ÂÃx@Ú˛àúÂô@˛
  3788. "8Âò@˛àòÂ@]ô8@˛
  3789. "8¯G˛àúÂMIJ
  3790. "8Â xJÄÄàòÂ@^f ÿMÄÄ
  3791. "8Âô xGÄàúÂô @Ä
  3792. "8Âx ˛àòÂ@^f ˛
  3793. "8¡¯˛àú²
  3794. "8Â8˛àòÂ@_3ò`˛
  3795. "8Âfx˛ˇÄ˛àúÂô
  3796. ˘
  3797. "8Â8˘àòÁ@@ ¯˘
  3798. "8‰Ã¯¿`˛àú˸      ›
  3799. &Xfi
  3800. x    )`‡3
  3801. x    )@‡ô
  3802. ))@fi
  3803. ∏Δ&@‡"⁄™ÿ†å††
  3804. ˇˇˇˇˇˇˇˇÑ`∫—≈ÿ∫“‘ˇª‘◊ˇº◊ÿˇΩ◊ÿˇæ÷◊ˇ¿—“’÷ˇ¡‘’ˇ¬”‘ˇƒ“”ˇ≈—“ˇˇ"Δ—Ù###˘
  3805. †°"ª’)ñ†ç°ñ°öf†ò
  3806. ¬ǬǰdONLNdˇˇ+“This line is a result of _DialogSelect calling 
  3807. †ô°öˇ˜f†ò°dONLNdˇˇ* _TEIdle†ô†ó†ç†É
  3808. IR°dONLNdÎî˜^(≤"Figure 1–Erroneous Insertion Point°dONLNd#(,63So the Dialog Manager, knowing that it allocated a ,
  3809. Courier°dONLNdVJ)˙TEHandle°dONLNd^J`)8 for °dONLNdc`⁄)an item that was visible,°dONLNd}î(86goes merrily on its way °dONLNdïî⁄)|?flashing the insertion point.  The problem is not simply one of°dONLNd’(Ä(D6appearance.  If a user °dONLNdÏÄ(⁄)hGhits a key, the Dialog Manager tries to process the key-down event just°dONLNd4)5C(Q6
  3810. as if the °dONLNd>(C4{)+EditText°dONLNdF){5√)8 item was still °dONLNdV)√5⁄)H:available, and this series of events causes a rather nasty°dONLNdë5A5(]6crash.°dONLNdòNZ{*HFortunately, the solution for this problem is a very simple one.  If an °dONLNd‡M{Y≥(vôEditText°dONLNdËN≥Z∏)8 °dONLNdÈN∏Z⁄)item is°dONLNdÒ[g[(É6hidden with a °dONLNdˇZ[f°)C
  3811. _HideDItem°dONLNd    [°g§)F °dONLNd
  3812. [§g⁄)Acall, the Dialog Manager does not consider it active and will not°dONLNdLhtF(ê6Atry to process key-down events for it.  So if your cdev contains °dONLNdçgFs~(êdEditText°dONLNdïh~t∂)8
  3813.  items, part °dONLNd¢h∂t⁄)8of your°dONLNd™uÅŸ(ù6+error handling should be to first hide the °dONLNd’tŸÄ)¡EditText°dONLNd›uÅH)8  items with °dONLNdÈuHÅr)7
  3814. a call to °dONLNdÛtrÄ∏)*
  3815. _HideDItem°dONLNd˝u∏Å⁄)F before°dONLNdÇéú(™6returning an error code or a °dONLNd"Åúç±)ÑNIL°dONLNd%DZé<) as the cdev’s function result.°dONLNdE≤æÇ(⁄6Further Reference: ›4›˘°dONLNdXø*À.+
  3816. •°dONLNdZø<Àç)Inside Macintosh°dONLNdjøçÀ')Q, Volume I, The Dialog Manager°dONLNdâÀ*◊.(ÛH•°dONLNdãÀ<◊ç)Inside Macintosh°dONLNdõÀç◊/)Q, Volume IV, The Dialog Manager°dONLNdª◊*„.(ˇH•°dONLNdΩ◊<„ç)Inside Macintosh°dONLNdÕ◊ç„!)Q, Volume V, The Control Panel ◊4◊˘
  3817. (Ï62) of 2(Ïà  Safe cdevsˇ◊#ˇ ˇˇˇˇ#◊†Ç 
  3818. /ZÅ#
  3819.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  3820. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  3821. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  3822. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  3823. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  3824.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  3825. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  3826. IR.°dONLNdn<ÅÛ(õZScript Manager Q&As
  3827. °dONLNdÄ<èZ*Text°dONLNdÄaè˛(´M.TX.ScriptMgr.Q&As
  3828. °dONLNd.õ<ßt(√Z Revised by:°dONLNd:õÑߡ)HDeveloper Support Center°dONLNdSõ±ß˛(√œ
  3829. November 1992°dONLNdaß<≥q(œZ Written by:°dONLNdmßÑ≥ˇ)HDeveloper Support Center°dONLNdÜßæ≥˛(œ‹ October 1990°dONLNdìø<À⁄(ÁZThis Technical Note contains a °dONLNd≤ø⁄À˛)û9collection of Q&As relating to a specific topic—questions°dONLNdÏÀ<◊†(ÛZGyou’ve sent the Developer Support Center (DSC) along with answers from °dONLNd3À†◊˛(Ûæthe DSC engineers.°dONLNdF◊<„u(ˇZ
  3830. While DSC °dONLNdP◊u„˛)9Lengineers have checked the Q&A content for accuracy, the Q&A Technical Notes°dONLNdù„<Ôq( Z don’t have °dONLNd®„qÔ˛)5Qthe editing and organization of other Technical Notes. The Q&A function is to get°dONLNd˙Ô<˚Ÿ(Znew technical information and °dONLNdÔŸ˚˛)ù6updates to you quickly, saving the polish for when the°dONLNdO˚<(#Z,information migrates into reference manuals.°dONLNd|<k*:Q&As are now included with Technical Notes to make access °dONLNd∂k˛(;âto technical updates easier for°dONLNd÷<+.(GZ/you. If you have comments or suggestions about °dONLNd.+˛)Ú*Q&A content or distribution, please let us°dONLNd0+<7\(SZknow °dONLNd5+\7˛) Iby sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical°dONLNd7<Ci(_Z9questions about Q&A content to DEVSUPPORT for resolution.°dONLNdπO<[«*NNew Q&As and Q&As revised this month are marked with a bar in the side margin."n  ÜXÜ
  3831. °dONLNdÄ<è÷*48Using FormatXToStr and FormatStrToX with Pascal switches
  3832. °dONLNdAè<õb* Written:°dONLNdJèàõ≤)L12/10/90°dONLNdSõ<ßÅ(√ZLast reviewed:°dONLNdbõàß¶)L8/1/92°dONLNdi≥<øV(€ZWhy °dONLNdm≥Vø˛)Pdo the FormatXToStr and FormatStrToX Script Manager routines stop working when I°dONLNdæø<À‹(ÁZuse the Pascal -MC68881 switch?°dONLNdfiÀ<◊N* ___°dONLNd‚„<Ô3*0Regular SANE extended numbers are 10 bytes long °dONLNd„3Ô˛)˜%while MC68881 extended numbers are 12°dONLNd8Ô<˚÷(ZTbytes long, and the extra two bytes are right in the middle of every 68881 extended °dONLNdåÔ÷˚˛(Ùnumber.°dONLNdî˚<∑(#ZEAppendix G “The SANE Library” in the Macintosh Programmer’s Workshop °dONLNdŸ˚∑˛(#’ (MPW) Object°dONLNdÊ<c(/Z;Pascal version 3.1 manual goes into detail about this. The °dONLNd!c˛(/ÅFormatX2Str and FormatStr2X°dONLNd=<X(;Zparse °dONLNdCX˛)Tthe extended number you pass them directly, and they can only parse 10-byte extended°dONLNdò<+fi(GZXnumbers. Fortunately, you can still use the -mc68881 option with these routines as long °dONLNdfi+˛(G¸as you°dONLNd˜+<7Ä(SZ convert any °dONLNd+Ä7˛)DBextended numbers to 80-bit extended numbers before passing them to°dONLNdF7<CÌ(_ZUFormatX2Str and FormatStr2X. The SANE.p unit has routines to do this called X96toX80 °dONLNdõ7ÌC˛(_ and°dONLNdüC<O‡(kZJX80toX96 (incorrectly documented as X96to80 and X80to96 in the MPW Object °dONLNdÈC‡O˛(k˛Pascal°dONLNdO<[§(wZmanual). Because the °dONLNdO§[˛)hFextended80 and extended96 types aren’t equivalent to the extended type°dONLNdL[<gY(ÉZas far °dONLNdS[Yg˛)Sas Object Pascal is concerned, you have to redeclare FormatX2Str and FormatStr2X to°dONLNdßg<s(èZ-take these types. You can do this as follows:,
  3833. Courier
  3834.     °dONLNd’<ä6*2FUNCTION FormatX2Str80 (x:             extended80;°dONLNd    â<îO*
  3835. 7                        myCanonical:   NumFormatString;°dONLNd    @ì<û;*
  3836. 3                        partsTable:    NumberParts;°dONLNd    tù<®w*
  3837. ?                        VAR outString:  Str255):  FormatStatus; ◊X◊
  3838. *(Script Manager Q&As(Ï1) of 7ˇ°¿Ù%%DSIDICT:_cv
  3839. currentdict /bu known {bu}if
  3840. userdict /_cv known not{userdict /_cv 30 dict put}if
  3841. _cv begin
  3842. /bdf{bind def}bind def
  3843. currentscreen/cs exch def/ca exch def/cf exch def
  3844. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  3845. /ss{//cf //ca //cs setscreen}bdf
  3846. /stg{ss setgray}bdf
  3847. /strgb{ss setrgbcolor}bdf
  3848. /stcmyk{ss cvcmyk}bdf
  3849. /min1{dup 0 eq{pop 1}if}bdf
  3850. end
  3851. currentdict /bn known {bn}if
  3852. †ø˙◊#ˇ ˇˇˇˇ#◊ 
  3853. IR,Times
  3854. .+6-Macintosh Technical Notes /4/˘,
  3855. Courier
  3856.     °dONLNd(«*#    INLINE $2F3C,$8210,$FFE8,$A8B5;°dONLNd$1<Ù*,FUNCTION FormatStr2X80 (source:      Str255;°dONLNdQ;F&*
  3857. 6                        myCanonical:  NumFormatString;°dONLNdàEP
  3858. *
  3859. 1                        partsTable:  NumberParts;°dONLNd∫OZX*
  3860. @                        VAR x:       extended80):  FormatStatus;°dONLNd˚Yd«*
  3861. #    INLINE $2F3C,$8210,$FFE6,$A8B5;
  3862. °dONLNdo{œ*`Call these routines instead of the originals. To call FormatX2Str80, all you have to do is this:
  3863.     °dONLNdÄáí'*VAR°dONLNdÑëú&*
  3864. 6   x:             extended80; {96-bit extended number}°dONLNdªõ¶¬*
  3865. "   myCanonical:   NumFormatString;°dONLNdfi•∞Æ*
  3866.    partsTable:    NumberParts;°dONLNd˝Ø∫ê*
  3867.    outString:     Str255°dONLNd√Œè*Kresult := FormatX2Str80 (X96toX80 (x), myCanonical, partsTable, outString);
  3868. °dONLNdbŸÂè*Calling FormatStr2X80 °dONLNdxŸèÂ⁄)w@is just slightly more complicated because the extended number is°dONLNdπÂÒx(
  3869. 6passed by reference:
  3870.     °dONLNdŒ˝'*VAR°dONLNd“*
  3871. 4   x:           extended;   {96-bit extended number}°dONLNd*
  3872. 4   x80:         extended80; {80-bit extended number}°dONLNd<&ã*
  3873.    source:      Str255;°dONLNdT%0Ω*
  3874. !   myCanonical:  NumFormatString;°dONLNdv/:§*
  3875.    partsTable:  NumberParts;°dONLNdìCN|*x80 := X96toX80 (x);°dONLNd®MXX*
  3876. @result := FormatStr2X80 (theString, realCanon, PartsTable, x80);°dONLNdÈWb|*
  3877. x := X80toX96 (x80);
  3878. °dONLNd˛myà*KYou should find that these calls now work properly with the -mc68881 option°dONLNdJyÖ—* _set. This of course means that you’ll need two versions of the source code; one with the calls °dONLNd©y—Ö⁄(°Ôto°dONLNd¨Öëø(≠6"convert between 96-bit and 80-bit °dONLNdŒÖøë⁄)ß5extended numbers for use with the -mc68881 option and°dONLNdëùæ(π6"another one which just uses plain °dONLNd&ëæù⁄)¶5old 80-bit extended numbers for use when the -mc68881°dONLNd\ù©w(≈6option is turned off.°dONLNdrµ¡9*X-Ref:°dONLNdy¡Õ‡* 'Inside Macintosh Volume VI, page 14-49.
  3879. °dONLNd°ŸËX*.String2Date and Date2Secs conversion surprises
  3880. °dONLNd–ËÙ>* Written:°dONLNdŸËdÙà)L9/17/91°dONLNd·Ù](6Last reviewed:°dONLNdÙdÇ)L8/1/92°dONLNd˜ 4(46;String2Date and Date2Secs treat all dates with the year 04 °dONLNd2 4⁄(4R to 10 as 2004 to 2010 instead of°dONLNdS$[(@6
  3881. 1904 to 1910.°dONLNda$0** ___°dONLNde<H8*@This is correct; the Script Manager treats two-digit years less °dONLNd•<8H⁄(dV!than or equal to 10 as 20xx dates°dONLNd«HTn(p6if the current year °dONLNd€HnT⁄)VKis between 1990 and 1999, inclusive. Basically, it just assumes that you’re°dONLNd'T`O(|6Dtalking about 1-20 years in the future, rather than 80-100 years in °dONLNdkTO`⁄(|mthe past. The same is true of°dONLNdâ`lh(à6Itwo-digit 9x dates, when the current year is less than or equal to xx10. °dONLNd“`hl⁄(àÜThus, in 2003, the date°dONLNdÍlxâ(î6returned when 3/7/94 °dONLNdˇlâx⁄)q>is converted will be 1994, not 2094. This is all documented in°dONLNd>xÑã(†6G“Worldwide Development: Guide to System Software,” available from APDA.
  3882. °dONLNdÜú´°*'FormatX2Str strings ◊4◊˘
  3883. *%2) of 7(ÏûScript Manager Q&Asˇ‘◊#ˇ ˇˇˇˇ#◊ 
  3884. IR,Times
  3885. .+Z-Developer Support Center(-‹
  3886. November 1992 /X/
  3887. °dONLNd<)b(EZWritten:°dONLNd    à)¨)L11/6/91°dONLNd)<5Å(QZLast reviewed:°dONLNd )à5¶)L8/1/92°dONLNd'A<MW(iZ7Using the Script Manager to convert numbers to strings °dONLNd^AWM˛(iu and vice versa, in any language,°dONLNdM<Ya(uZwhat’s °dONLNdÜMaY˛)%Pthe best way to create the string to pass to FormatX2Str? Will strings using the°dONLNd◊Y<e+(ÅZ4characters: “#” or “0” or “.” or “,” work no matter °dONLNd Y+e˛)Ô-what script is currently running, and if not,°dONLNd9e<qÅ(çZwhat can I do?°dONLNdHq<}N* ___°dONLNdLâ<ï‘*PThe number format string and canonical number format string mechanisms that you °dONLNdúâ‘ï˛(±Úuse with°dONLNd•ï<°≤(ΩZFormatX2Str and its kin °dONLNdΩï≤°˛)vEis a strange design, for exactly the reason that you asked about. The°dONLNd°<≠W(…Z:number format string (the one with the characters such as °dONLNd=°W≠˛(…u!“#” and “0”) does not necessarily°dONLNd_≠<π>(’Z6work right regardless of the current script. In fact, °dONLNdï≠>π˛(’\&it doesn’t even necessarily work right°dONLNdºπ<≈(·Z-between localized versions within one script °dONLNdÈπ≈˛)”/system. The canonical number format string does°dONLNd≈<—}(ÌZ?work between localized systems and between script systems. The °dONLNdX≈}—˛(Ìõstrange thing is there’s an°dONLNdt—<›£(˘ZLeasy way to store number format strings (usually in a 'STR ' resource), but °dONLNd¿—£›˛(˘¡no obvious way to°dONLNd“›<ÈW(Z7store canonical number format strings. Here’s what you °dONLNd    ›WÈ˛(ucan do when converting between°dONLNd(È<ıü(Znumbers and strings:°dONLNd=<
  3888. Ø*LWhen you convert a number format string to a canonical number format string °dONLNdâØ
  3889. ˛()Õwith Str2Format°dONLNdô
  3890. <ñ(5Zon a U.S. system, °dONLNd´
  3891. ñ˛)ZIit converts it from something like “###.###” to a canonical number format°dONLNdı<%F(AZ;string that looks something like, “three digits, a decimal °dONLNd0F%˛(Ad%point, and three digits.” On a German°dONLNdV%<1)(MZ-system, that same number format string would °dONLNdÉ%)1˛)Ì*be converted to “three digits, a thousands°dONLNdÆ1<=ø(YZseparator, and three digits.”°dONLNdÃI<U˚*)What you can do to get around this is to °dONLNdıI˚U˛)ø5save the canonical number format string in a resource°dONLNd+U<aÆ(}ZKinstead of the number format string. The canonical string stores things in °dONLNdvUÆa˛(}Ãa language- and°dONLNdÜa<mÍ(âZ$script-independent way. Create this °dONLNd™aÍm˛)Æ:resource by writing a trivial utility program that takes a°dONLNdÂm<y(ïZ-number format string and calls Str2Format to °dONLNdmy˛)ÿ1convert it into a canonical number format string,°dONLNdDy<ÖÅ(°Zand then copy °dONLNdRyÅÖ˛)ENthis into a handle and save it as a resource of a custom type, like 'NUMF'. In°dONLNd°Ö<ëò(≠Zyour real program, °dONLNd¥Öòë˛)\Hload the 'NUMF' resource, lock it, and then pass the dereferenced handle°dONLNd˝ë<ù·(πZto FormatX2Str and FormatStr2X.°dONLNd©<µv*?You can see this done in the ProcDoggie Process Manager sample °dONLNd\©vµ˛(—îfrom the 7.0 Golden Master°dONLNdwµ<¡©(›ZCD. Take a look at the °dONLNd鵩¡˛)mCSetUpProcessInfoItems procedure in UProcessGuts.inc1.p file. You’ll°dONLNd“¡<Õÿ(ÈZTsee that the 'NUMF' resource is loaded, locked, and then passed to FormatX2Str. The °dONLNd    &¡ÿÕ˛(Ȉ    result is°dONLNd    0Õ<Ÿ(ıZ,displayed in the Process Information window.°dONLNd    ]Â<Ò}*?If your program is localized by nonprogrammers, then you might °dONLNd    úÂ}Ò˛(
  3892. õwant to provide the utility°dONLNd    ∏Ò<˝™(Zthat converts a number °dONLNd    œÒ™˝˛)nGformat string to a canonical number format string resource just in case°dONLNd
  3893. ˝<    Ï(%Z&they have to change the entire format °dONLNd
  3894. =˝Ï    ˛)∞7of the string. Then they can install the new 'NUMF' (or°dONLNd
  3895. u    <r(1ZBwhatever you choose) resource as part of the localization process.
  3896. °dONLNd
  3897. ∏-<<Ö*'1Code for truncating a multi-byte character string
  3898. °dONLNd
  3899. Í<<Hb* Written:°dONLNd
  3900. Û<àH¨)L1/24/92°dONLNd
  3901. ˚H<TÅ(pZLast reviewed:°dONLNd
  3902. HàT¶)L8/1/92°dONLNd `<le(àZ=I create a Macintosh file name from another file name. Since °dONLNd N`el˛(àÉI am adding information to the°dONLNd ml<xÅ(îZ>name, I must make sure that it is within the 31 chars maximum °dONLNd ´lÅx˛(îüallowed by the operating°dONLNd ƒx<Ñ(†Z)system. What I need is the equivalent of °dONLNd ÌxÑ˛)»0the TruncText command, except instead of dealing°dONLNd Ñ<ê.(¨Z3with pixel width, I want the width to be number of °dONLNd QÑ.ê˛)Ú,characters (31). I can trunc myself, but I’d°dONLNd ~ê<úë(∏ZHrather do a proper “smTruncMiddle” and have it nicely internationalized.°dONLNd «ú<®N* ___ ◊X◊
  3903. *(Script Manager Q&As(Ï3) of 7ˇö◊#ˇ ˇˇˇˇ#◊ 
  3904. IR,Times
  3905. .+6-Macintosh Technical Notes /4/˘
  3906. °dONLNd)5N*$CIf you’re going to be adding a set number of bytes to the end of a °dONLNdC)N5⁄(Qlexisting string and you don’t°dONLNda5AG(]6?want the localized ellipsis (from the 'itl4' resource) between °dONLNd†5GA⁄(]ethe truncated string and your°dONLNdæAM¬(i6%bytes, then you can use this routine:,
  3907. Courier
  3908.     °dONLNd‰Ydg*CPROCEDURE TruncPString (VAR theString: Str255; maxLength: Integer);°dONLNd(cnÖ*
  3909. I{ This procedure truncates a Pascal string to be of length maxLength or }°dONLNdrmxv*
  3910. F{ shorter. It uses the Script Manager charByte function to make sure }°dONLNdπwÇq*
  3911. E{ the string is not broken in the middle of a multi-byte character. }°dONLNdˇÅå1*
  3912.   VAR°dONLNdãñÜ*
  3913.     charType: Integer;°dONLNdï†;*
  3914.   BEGIN°dONLNd$ü™Â*
  3915. )    IF Length(theString) > maxLength THEN°dONLNdN©¥O*
  3916.       BEGIN°dONLNdZ≥æ+*
  3917. 7        charType := CharByte(@theString[1], maxLength);°dONLNdíΩ»Ä*
  3918. H        WHILE ((charType < 0) OR (charType > 1)) AND (maxLength <> 0) DO°dONLNd€«“c*
  3919.           BEGIN°dONLNdΗ‹€*
  3920. '            maxLength := maxLength - 1;°dONLNd€Ê?*
  3921. ;            charType := CharByte(@theString[1], maxLength);°dONLNdOÂ^*
  3922.           END;°dONLNd^Ô˙€*
  3923. '        theString[0] := chr(maxLength);°dONLNdܢJ*
  3924.  
  3925.       END;°dONLNdë6*
  3926.   END;
  3927. °dONLNdò%î*If you want the localized °dONLNd≤î%⁄)|Dellipsis (from the 'itl4' resource) between the truncated string and°dONLNd˜%1L(M6Dyour bytes, or you want the localized ellipsis in the middle of the °dONLNd;%L1⁄(Mjcombined strings truncated to°dONLNdY1=ı(Y61a specific length, then you can use this routine:
  3928.     °dONLNdãIT]*AFUNCTION TruncPString (maxLength: Integer; VAR theString: Str255;°dONLNdŒS^∏*
  3929.  truncWhere: TruncCode): Integer;°dONLNdÔ]hÄ*
  3930. H{ This function truncates a Pascal String to be of length maxLength or }°dONLNd8gr{*
  3931. G{ shorter. It uses the Script Manager TruncString function which adds }°dONLNdÄq|q*
  3932. E{ the correct tokenEllipsis to the middle or end of the string. See }°dONLNdΔ{Üg*
  3933. C{ Inside Macintosh Volume VI, pages 14-59 and14-60 for more info. }°dONLNd
  3934. Öê1*
  3935.   VAR°dONLNdèöw*
  3936.     found: Boolean;°dONLNd$ô§«*
  3937. #    first, midPoint, last: Integer;°dONLNdH£Æã*
  3938.     tempString: Str255;°dONLNd`≠∏ö*
  3939.     whatHappened: Integer;°dONLNd{∑¬;*
  3940.   BEGIN°dONLNdÉ¡Ãw*
  3941.     found := FALSE;°dONLNdóÀ÷c*
  3942.     first := 0;°dONLNdß’‡?*
  3943. ;    last := TextWidth(@theString[1], 0, Length(theString));°dONLNd„flÍÂ*
  3944. )    IF Length(theString) > maxLength THEN°dONLNd
  3945. ÈÙO*
  3946.       BEGIN°dONLNdÛ˛˛*
  3947. .        WHILE (first <= last) AND NOT found DO°dONLNdH˝c*
  3948.           BEGIN°dONLNdXÄ*
  3949. H            tempString := theString; { tempString gets destroyed every }°dONLNd°!*
  3950. 5                                     { time through }°dONLNd◊&˘*
  3951. -            midPoint := (first + last) DIV 2;°dONLNd%0ä*
  3952. J            whatHappened := TruncString(midPoint, tempString, truncWhere);°dONLNdP/:
  3953. *
  3954. 1            IF whatHappened < smNotTruncated THEN°dONLNdÇ9DÔ*
  3955. +              BEGIN { ERROR, bail out now }°dONLNdÆCNN*
  3956. >                TruncPString := whatHappened; { return error }°dONLNdÌMX«*
  3957. #                Exit(TruncPString);°dONLNd    Wbm*
  3958.               END°dONLNd    #al+*
  3959. 7            ELSE IF Length(tempString) = maxLength THEN°dONLNd    [kvü*
  3960.               found := TRUE°dONLNd    wuÄ+*
  3961. 7            ELSE IF Length(tempString) > maxLength THEN°dONLNd    Øä¬*
  3962. "              last := midPoint - 1°dONLNd    “âîh*
  3963.             ELSE°dONLNd    „ìûÃ*
  3964. $              first := midPoint + 1;°dONLNd
  3965. ù®^*
  3966.           END; ◊4◊˘
  3967. *(4) of 7(ÏûScript Manager Q&Asˇ
  3968. >◊#ˇ ˇˇˇˇ#◊ 
  3969. IR,Times
  3970. .+Z-Developer Support Center(-‹
  3971. November 1992 /X/,
  3972. Courier
  3973.     °dONLNd<(‹(DZ         theString := tempString;°dONLNd!'<2ê*
  3974. D        TruncPString := whatHappened; { will always be smTruncated }°dONLNdf1<<J*
  3975. 6                                      { in this case }°dONLNdù;<Fi*
  3976.           END°dONLNdßE<Pd*
  3977.     ELSE°dONLNd∞O<Zê*
  3978. D      TruncPString := smNotTruncated; { the string wasn't too long }°dONLNdıY<dZ*
  3979.   END;
  3980. °dONLNd¸{<ä¡*&9Character type and subtype values within the Kanji system
  3981. °dONLNd6ä<ñb* Written:°dONLNd?äàñ≤)L11/17/89°dONLNdHñ<¢Å(æZLast reviewed:°dONLNdWñࢶ)L8/1/92°dONLNd^Æ<∫»(÷ZRWhat are the values of character type and subtype with the Macintosh Kanji system?°dONLNd±∫<ΔN* ___°dONLNdµ“<fi(*2For Roman, these are the values of character type:
  3982.     °dONLNdËÍ<ıπ*    Punctuation         0°dONLNdÙ<ˇπ*
  3983.     ASCII               1°dONLNd˛<    π*
  3984.     European            7
  3985. °dONLNd6< ä*FFor KanjiTalk, the values are the same as Roman, with the addition of:
  3986.     °dONLNd},<7π*    Katakana            2°dONLNdó6<Aπ*
  3987.     Hiragana            3°dONLNd±@<Kπ*
  3988.     Kanji               4°dONLNdÀJ<Uπ*
  3989.     Greek               5°dONLNdÂT<_π*
  3990.     Russian (Cyrillic)  6
  3991. °dONLNdˇj<v*.In Roman, the subtype field is interpreted as:
  3992.     °dONLNd.Ç<çπ*    Normal punctuation  0°dONLNdHå<óπ*
  3993.     Numeric             1°dONLNdbñ<°π*
  3994.     Symbols             2°dONLNd|†<´π*
  3995.     Blanks              3
  3996. °dONLNdñ∂<¬É*The KanjiTalk °dONLNd§∂ɬ˛)GNsubtype values are the same as Roman except if the character type is Kanji, in°dONLNdÛ¬<Œ(ÍZ0which case the subtype field takes these values:
  3997.     °dONLNd$⁄<Âπ*    JIS Level 1         0°dONLNd>‰<Ôπ*
  3998.     JIS Level 2         1°dONLNdXÓ<˘π*
  3999.     JIS User Character  2
  4000. °dONLNdr<˜*_Finally, for KanjiTalk, the character direction field is replaced by the In-ROM field. It is 1 °dONLNd—˜˛(,if°dONLNd‘<%(8Z1the character is in the ROM card and 0 otherwise. ◊X◊
  4001. *¥Script Manager Q&As(Ï5) of 7ˇ◊#ˇ ˇˇˇˇ#◊ 
  4002. IR,Times
  4003. .+6-Macintosh Technical Notes /4/˘
  4004. °dONLNd)8[*'-Script Manager NMeasureJust documentation fix
  4005. °dONLNd.8D>* Written:°dONLNd78dDà)L7/21/92°dONLNd?DP](l6Last reviewed:°dONLNdNDdPà)L9/15/92°dONLNdV\hN(Ñ6 The Script °dONLNda\Nh⁄)6KManager’s NMeasureJust call seems to work differently depending on our main°dONLNd≠ht≠(ê6script (Roman versus Hebrew, °dONLNd h≠t⁄)ï?for example). Please take a look at the following code and tell°dONLNd
  4006. tĪ(ú6 me if I’m doing something wrong:,
  4007. Courier
  4008.     °dONLNd+åó*{°dONLNd-ñ°;*
  4009.    ....°dONLNd5†´w*
  4010.    Fixed slop  = 0;°dONLNdI™µü*
  4011.    Point   numer   = {1,1};°dONLNde¥øü*
  4012.    Point   denom   = {1,1};°dONLNdÅæ…è*
  4013. K   ::NMeasureJust ((Ptr) charBuffer, (short) charCount,slop,(Ptr) charLocs,°dONLNdÕ»”!*
  4014. 5                       smOnlyStyleRun, numer, denom);°dONLNd“›Å*
  4015.    if (charLocs[0]) {°dONLNd‹Áô*
  4016. M       // Under Hebrew system NMeasureJust acts differently than described in°dONLNdgÊÒ∑*
  4017. S       // Inside Macintosh Volume VI; first entry in charLocs array containes width°dONLNdª˚î*
  4018. L       // of last character and last entry in charLocs array containes zero.°dONLNd˙Â*
  4019. )       charLocs[charCount] = charLocs[0];°dONLNd2ã*
  4020.        charLocs[0] = 0;°dONLNdJ1*
  4021.    };°dONLNdP#;*
  4022.    ....°dONLNdX"-*
  4023. }
  4024. °dONLNdZ,8** ___°dONLNd^DP≈*#The truth is that Inside Macintosh °dONLNdÅD≈P⁄)≠3Volume VI is incorrect, and NMeasureJust is working°dONLNdµP\ñ(x6correctly, even though the °dONLNd–Pñ\⁄)~?results seem to defy any kind of sense. Here’s how NMeasureJust°dONLNd\h9(Ñ6works:°dONLNdtÄ_*
  4025. NMeasureJust °dONLNd$t_Ä⁄)GRactually puts into the first entry of the charLocs array the pixel offset from the°dONLNdwÄå+(®6left °dONLNd|Ä+å⁄)[end of the text to the leading edge of the first character, regardless of the active script°dONLNdÿåòy(¥6system. For Roman °dONLNdÍåyò⁄)aHtext in a Roman script system, that’s easy: it’s always zero. For Hebrew°dONLNd3ò§x(¿6Ntext in a Hebrew script system, the leading edge of the first character is on °dONLNdÅòx§⁄(¿ñthe right edge of the°dONLNdó§∞V(Ã6Dtext, so NMeasureJust puts the pixel distance between the left edge °dONLNd€§V∞⁄(Ãtof the text to the right edge°dONLNd˘∞ºΩ(ÿ6Sof the text——the same thing as the entire width of the text. Each successive entry °dONLNdL∞Ωº⁄(ÿ€in the°dONLNdSº»P(‰6@charLocs array is smaller than the previous entry because we’re °dONLNdìºP»⁄(‰ngradually moving to the left°dONLNd∞»‘(64edge of the text as we move through each successive °dONLNd‰»‘⁄(;(character. The trailing edge of the last°dONLNd
  4026. ‘‡¡(¸6acharacter is at the left edge of the string, and so the last entry in the charLocs array is zero.°dONLNdoϯv*CWhat if you pass in text that contains both Roman and Hebrew text? °dONLNd≤Ïv¯⁄(îThis text contains a°dONLNd«¯»( 6Vdirection boundary, and NMeasureJust can sense this. For this case, NMeasureJust puts °dONLNd¯»⁄( Êinto°dONLNd"ò(,6the charLocs array a series °dONLNd>ò⁄)ÄFof decreasing values for the right-to-left characters, and a series of°dONLNdÖ˙(863increasing values for the left-to-right characters.°dONLNdπ(4i*BYou’re probably passing Roman text (ASCII codes less than 127) to °dONLNd˚(i4⁄(PáNMeasureJust with the°dONLNd    4@b(\6Hebrew script °dONLNd    4b@⁄)JJsystem active to get the results that you reported. This case includes two°dONLNd    j@L>(h6@direction boundaries: one at the beginning that’s right-to-left °dONLNd    ™@>L⁄(h\and contains no characters, one°dONLNd     LX6(t6=that’s left-to-right and contains all your Roman characters, °dONLNd
  4027. L6X⁄(tT$and finally one that’s right-to-left°dONLNd
  4028. ,Xd·(Ä6,and contains no characters. The first entry °dONLNd
  4029. XX·d⁄)…6in the charLocs array measures the first right-to-left°dONLNd
  4030. èdpù(å6direction run even though it °dONLNd
  4031. ¨dùp⁄)ÖDcontains no characters, and so it contains the position of the right°dONLNd
  4032. Òp|ö(ò6Tedge of your text. The last entry in the charLocs array is zero because it measures °dONLNd Epö|÷(ò∏the last right°dONLNd Sp÷|⁄)<-°dONLNd T|àc(§6to-left direction °dONLNd f|cà⁄)KMrun, which again contains no characters. All the charLocs entries between the°dONLNd ¥àî‹(∞6,first and the last measure the positions of °dONLNd ‡à‹î⁄)ƒ5the left-to-right, Roman characters, and so you get a°dONLNd (º6*series of increasing values. This is just °dONLNd @⁄)¡6a special case of passing text that contains direction°dONLNd w†¨£(»6boundaries to NMeasureJust. ◊4◊˘
  4033. *$6) of 7(ÏûScript Manager Q&Asˇû◊#ˇ ˇˇˇˇ#◊ 
  4034. IR,Times
  4035. .+Z-Developer Support Center(-‹
  4036. November 1992 /X/
  4037. °dONLNd5<D∫(`Z6Interfacing a Macintosh application with Map CDEV data"TW
  4038. °dONLNd7D<Pb* Written:°dONLNd@DàP¨)L8/17/92"cW °dONLNdHP<\Å(xZLast reviewed:°dONLNdWPà\≤)L10/11/92"oW "{W °dONLNd`h<tú(êZHow can I provide °dONLNdrhút˛)`Emy users with a “hook” to access the geographical database in Apple’s"áW °dONLNd∏t<Ä(úZ(“Map” Control Panel from my application?"ìW °dONLNd·Ä<åN* ___"üW "´W °dONLNdÂò<§“*There’s no supported way of °dONLNdò“§˛)ñ:accessing the geographical database contained in the “Map”"∑W °dONLNd<§<∞§(ÃZMControl Panel. Here are some hints, however (just to satisfy your curiosity):"√W "œW °dONLNdäº<»†*GThe data are stored in a resource of type 'CTY#', ID=-4064, in the Map °dONLNd—º†»˛(‰æcdev. The resource"€W °dONLNd‰»<‘´(Zformat is a list of word °dONLNd˝»´‘˛)oIaligned (variable length) city entries, preceded by an integer indicating"ÁW °dONLNdG‘<‡(¸Z0the number of entries. Each entry has the format"ÛW "ˇW °dONLNdxÏ<¯Ú** [Integer]    length in bytes of the entry" W °dONLNd§¯<Ò* ) [Longint]   latitude in Fract; north = +"W °dONLNdŒ<Ù* ) [Longint]   longitude in Fract; east = +"#W °dONLNd¯<"* 0 [Longint]   GMT difference in seconds; east = +"/W °dONLNd)<( *   [Longint]  (reserved; set to 0)";W °dONLNdJ(<4◊* " [PascalString]  name of the city."GW  ◊X◊
  4039. (ÏZScript Manager Q&As(Ï7) of 7ˇ“◊#ˇ ˇˇˇˇ#◊†Ç 
  4040. /ZÅ#
  4041.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4042. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4043. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4044. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4045. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4046.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4047. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  4048. IR.°dONLNdz<ç(ßZScript Manager Variables
  4049. °dONLNdå<õZ*Text°dONLNdååõ˛(∑™M.TE.ScriptVars
  4050. °dONLNd/ß<≥q(œZ Written by:°dONLNd;ßÑ≥
  4051. )HJohn Harvey & Peter Edberg°dONLNdVßÕ≥˛(œΠ   June 1989°dONLNd`ø<À¶(ÁZPThis Technical Note describes, in detail, the local and global script variables. ˆXˆ
  4052. °dONLNd±<ˇè*4 Introduction
  4053. °dONLNdæ <(*0The Script Manager maintains a number of global °dONLNdÓ (˛)Ï,variables which can be read with the routine,
  4054. Courier°dONLNd<#ê(@Z _GetEnvirons°dONLNd'ê$ö)T.  °dONLNd*ö$¶)
  4055. 7These variables can be set by a corresponding routine, °dONLNda¶#˙(@ƒ _SetEnvirons°dONLNdm˙$˛)T.°dONLNdp$<0é(LZIn addition, each °dONLNdÇ$é0˛)RNscript interface system maintains variables of its own.  These are referred to°dONLNd—0<<~(XZAas local variables in Inside Macintosh, Volume V-293, The Script °dONLNd0~<˛(XúManager, and are read by°dONLNd+<<HÇ(eZ
  4056. _GetScript°dONLNd5=ÇI∏)F  and set by °dONLNdA<∏H˛)6
  4057. _SetScript°dONLNdK=˛I)F.°dONLNdMU<a◊(}Z#Think of it like this:  the Script °dONLNdpU◊a˛)õ:Manager maintains an environment in which different script°dONLNd´a<m (âZ.interfaces can run.  The global variables are °dONLNdŸa m˛)–1used to set up and maintain the environment (thus°dONLNd n<zÇ(ñZthe names for °dONLNdnÇz¿)F
  4058. the routines °dONLNd&m¿y)> _GetEnvirons°dONLNd2nz/)T and °dONLNd7m/yÉ) _SetEnvirons°dONLNdCnÉz˛)T), and the local variables°dONLNd^{<á(£Z0control how the script itself works (so we have °dONLNdézÜc)·
  4059. _GetScript°dONLNdò{cáz)F and °dONLNdùzzÜ¿)
  4060. _SetScript°dONLNdß{¿á»)F).
  4061. °dONLNd™ü<ƨ( ZGlobal Variables
  4062. °dONLNdªª<«è*When you call °dONLNd…∫èΔ„)S _GetEnvirons°dONLNd’ª„«˚)T or °dONLNdŸ∫˚ΔA)
  4063. _GetScript°dONLNd„ªA«ì)F, you describe °dONLNdÚªì«˛)Rthe variable you are°dONLNd«<”¬(ÔZinterested in with a verb.  A °dONLNd%«¬”˛)Ü@verb is simply an integer constant which the Script Manager uses°dONLNdf”<fl (˚Z1to figure out which variable you want to read or °dONLNdó” fle)‰set.  The z in °dONLNd¶”efl∑)EInside Macintosh°dONLNd∂”∑fl˛)R, V-313, gives°dONLNd≈‡<Ï£(Zincorrect names and °dONLNdŸ‡£Ï9)gdescriptions for some of the °dONLNdˆfl9Îç)ñ _GetEnvirons°dONLNd‡çÏ™)T and °dONLNdfl™Î˛) _SetEnvirons°dONLNdÏ<¯(Z.verbs.  Table 1 provides correct descriptions. ◊X◊
  4064. *ÿScript Manager Variables(Ïˇ1) of 10ˇ°¿Ù%%DSIDICT:_cv
  4065. currentdict /bu known {bu}if
  4066. userdict /_cv known not{userdict /_cv 30 dict put}if
  4067. _cv begin
  4068. /bdf{bind def}bind def
  4069. currentscreen/cs exch def/ca exch def/cf exch def
  4070. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4071. /ss{//cf //ca //cs setscreen}bdf
  4072. /stg{ss setgray}bdf
  4073. /strgb{ss setrgbcolor}bdf
  4074. /stcmyk{ss cvcmyk}bdf
  4075. /min1{dup 0 eq{pop 1}if}bdf
  4076. end
  4077. currentdict /bn known {bn}if
  4078. †øƒ◊#ˇ ˇˇˇˇ#◊ 
  4079. IR,Times
  4080. .+6-Macintosh Technical Notes /4/˘
  4081. °dONLNd)<5n+$$Constant°dONLNd    )ü5ø)cValue°dONLNd)fi5)?Meaning TXTµ,
  4082. Courier°dONLNd6<B{(_Z    smVersion°dONLNd!7¨C≤)p0°dONLNd#7fiCs)2Script Manager version number°dONLNdAC<Ot(lZsmMunged°dONLNdJD¨P≤)p2°dONLNdLDfiPY)2Global modification count°dONLNdfP<\{(yZ    smEnabled°dONLNdpQ¨]≤)p4°dONLNdrQfi]ä)2%Script count; 0 if Script Manager not°dONLNdö]fii* enabled°dONLNd¢i<uÇ(íZ
  4083. smBidirect°dONLNd≠j¨v≤)p6°dONLNdØjfivL)2Bidirectional script flag°dONLNd…Ç<éâ(´Z smFontForce°dONLNd’ɨè≤)p8°dONLNd◊Éfiè$)2Force font flag°dONLNdÁè<õâ(∏Z smIntlForce°dONLNdÛê¨ú∏)p10°dONLNdˆêfiúp)2"Force international utilities flag°dONLNdú<®t(≈ZsmForced°dONLNd"ù¨©∏)p12°dONLNd%ùfi©ç)2&Current script forced to system script°dONLNdL©<µ{(“Z    smDefault°dONLNdV™¨∂∏)p14°dONLNdY™fi∂~)2!Current script defaulted to Roman°dONLNd}∂fi¬¯* script°dONLNdѬ<Œm(ÎZsmPrint°dONLNdå√¨œ∏)p16°dONLNdè√fiœ4)2Print action vector°dONLNd£€<Áâ(Z smSysScript°dONLNdØ‹¨Ë∏)p18°dONLNd≤‹fiËK)2Preferred system script°dONLNd Ë<Ùê(Z smLastScript°dONLNd◊Ȩı∏)p20°dONLNd⁄Èfiı>)2Last keyboard script°dONLNdÔı<â(Z smKeyScript°dONLNd˚ˆ¨∏)p22°dONLNd˛ˆfi*)2Keyboard script°dONLNd<t(7ZsmSysRef°dONLNd¨∏)p24°dONLNdfi#)2System folder °dONLNd(#b)E    volRefNum°dONLNd2<'Ç(DZ
  4084. smKeyCache°dONLNd=¨(∏)p26°dONLNd@fi(G)2[Obsolete, do not use]°dONLNdW(<4{(QZ    smKeySwap°dONLNda)¨5∏)p28°dONLNdd)fi5ã)2!Keyboard swapping resource handle°dONLNdÜA<MÇ(jZ
  4085. smGenFlags°dONLNdëB¨N∏)p30°dONLNdîBfiN)2
  4086. General flags°dONLNd¢N<ZÇ(wZ
  4087. smOverride°dONLNd≠O¨[∏)p32°dONLNd∞Ofi[>)2Script override flags°dONLNdΔ[<gó(ÑZ
  4088. smCharPortion°dONLNd‘\¨h∏)p34°dONLNd◊\fihì)2%Ch vs Sp Extra proportion, 4.12 fixed áXáµ°dONLNd˝uhÅâ(ùÜ/Table 1–Verbs for _GetEnvirons and _SetEnvirons°dONLNd-ô•Ã(¡6*The descriptions in the table are still a °dONLNdWôÕ⁄)¥9bit sketchy.  The next section describes each variable in°dONLNd땱˛(Õ62more detail and describes the size of each global.°dONLNdƒæ ê*Byte or word globals are °dONLNd›æê n)x,mapped to the low-order byte or word of the °dONLNd    Ωn…ü)fiLongInt°dONLNdæü ⁄)1  returned by°dONLNd ÷l(Û6 _GetEnvirons°dONLNd)Àl◊ó)T8, with the high-order parts set to zero. Similarly, for °dONLNdaÀó◊⁄(Ûµ
  4089. these globals°dONLNdo◊„l(6 _SetEnvirons°dONLNd{ÿl‰w)T9 ignores all but the appropriate part (low-order byte or °dONLNd¥ÿw‰⁄(ïword) of its params°dONLNd»‰5( 6value.°dONLNdœ¸<{+$    Verb Name°dONLNdŸ¸®»)lBytes°dONLNdfl¸R)HBrief Description°dONLNdÒ< {(=Z    smVersion°dONLNd˚®!Æ)l2°dONLNd˝!Ö)HScript Manager version number°dONLNd.:/(V6=At boot time, the version global is initialized to the value °dONLNdX-/9g(VMSMgrVers°dONLNd`.g:⁄)8.  The high byte is the°dONLNdx:Fõ(b6major version number and °dONLNdë:õF⁄)É?is defined in the MPW interface files.  The low byte is updated°dONLNd—FR(n60when any changes are made to the Script Manager.°dONLNd^<jt+$smMunged°dONLNd _®kÆ)l2°dONLNd
  4090. _kk)HGlobal modification count°dONLNd'wÉ{(ü6KThe munged global is initialized to zero at boot time and incremented when:°dONLNdsÑ*ê.+
  4091. •°dONLNduÉ7è})
  4092. _KeyScript°dONLNdÑ}êÖ)F °dONLNdÄÑÖêO)#changes the key script and updates °dONLNd£ÉOèú)  smKeyScript°dONLNdÆÑúê∂)M and°dONLNd≥ê7úã(πU smLastScript°dONLNd¿ù*©.(≈H•°dONLNd¬ú7®ã)
  4093. _SetEnvirons°dONLNdŒùã©R)T* is used to change a Script Manager global ◊4◊˘
  4094. (Ï62) of 10(ÏìScript Manager Variablesˇ`◊#ˇ ˇˇˇˇ#◊ 
  4095. IR,Times
  4096. .+Z-Developer Support Center(-Û    June 1989 /X/,
  4097. Courier
  4098. °dONLNd)`5ü(R~    smEnabled°dONLNd
  4099. *Ã6“)l1°dONLNd *6Á)H-Script count; 0 if Script Manager not enabled°dONLNd:B<N≈(jZTAt boot time or switch-launch time, the enabled global is initialized to zero, then °dONLNdéB≈N˛(j„ incremented°dONLNdöN<Z°(vZfor each script that is °dONLNd≤N°Z˛)eFinstalled and enabled.  Since the Roman script system should always be°dONLNd˘Z<f˛(ÇZbinstalled by the Script Manager, a value of zero indicates that the Script Manager is not enabled.°dONLNd\s<b*=It should be noted that older versions of the Script Manager °dONLNdôsbµ(õÄtreated this as a °dONLNd´rµ~Ê)SBoolean°dONLNd≤sÊ˛)1.  In°dONLNd∏Ä<å (®Z(other words, if there was more than one °dONLNd‡Ä å])–script installed, °dONLNdÚ]ã˛)Q_GetEnvirons(smEnabled)°dONLNd
  4100. ç<ô≤(µZwould return 255 (when °dONLNd!å≤ò)v _GetEnvirons°dONLNd-çô5)T  returns a °dONLNd8å5òf)/Boolean°dONLNd?çfôÈ)1 value $FF represents true).°dONLNd\•<±˘(ÕZ(For this reason, when testing to see if °dONLNdÑ•˘±˛)Ω8more than one script is installed, it is best to test as°dONLNdΩ±<Ωc(ŸZfollows:
  4101.     °dONLNd«…`‘7+$+scriptsinstalled := GetEnvirons(smEnabled);°dONLNdÙ”`fiÏ*
  4102. IF scriptsinstalled > 1 THEN°dONLNd›`Ëd*
  4103. 4{more than one script available, use Chartype, etc.}
  4104. °dONLNdIÛ`ˇ¶*
  4105. smBidirect°dONLNdTÙÓ)l1°dONLNdVÙÇ)HBidirectional script flag°dONLNdp <⁄(4Z#The bidirectional global indicates °dONLNdì ⁄˛)ûBthat at least one bidirectional script is installed.  It should be°dONLNd÷<$Ÿ(@ZXset to true ($FF) by the Arabic and Hebrew script systems.  This is not presently done, °dONLNd.Ÿ$˛(@˜but will°dONLNd7$<0 (LZ1be corrected in future versions of these systems.°dONLNdi<`H≠+$ smFontForce°dONLNdu=ÃI“)l1°dONLNdw=IZ)HForce font flag°dONLNdáI`U≠(r~ smIntlForce°dONLNdìJÃV“)l1°dONLNdïJV¶)H"Force international utilities flag°dONLNd∏V`bò(~smForced°dONLNd¡WÃc“)l1°dONLNd√Wc√)H&Current script forced to system script°dONLNdÍc`oü(å~    smDefault°dONLNdÙdÃp“)l1°dONLNdˆdp—)H(Current script defaulted to Roman script°dONLNd}<â}(•ZAt boot time, °dONLNd-|}àº)A    FontForce°dONLNd6}ºâ”)? and °dONLNd;|”à)    IntlForce°dONLNdD}âa)? are set from the °dONLNdV|aàã)O'itlc'°dONLNd\}ãâ‘)* resource, and °dONLNdk|‘à˛)IForced°dONLNdrä<ñQ(≤Zand °dONLNdvâQïÇ)Default°dONLNd}äÇñz)16 are set to zero.  These are all flags with the value °dONLNd≥äzñ˛)¯zero for false and $FF for°dONLNdŒó<£Z(øZtrue. °dONLNd‘óZ£c) °dONLNd’ñc¢¢)        FontForce°dONLNdfió¢£≈)? and °dONLNd„ñ≈¢)#    IntlForce°dONLNdÏó£≠)? control the operation of the °dONLNd
  4106. ñ≠¢˙)© _FontScript°dONLNdó˙£˛)M,°dONLNd£<Øê(ÃZ _Font2Script°dONLNd#§ê∞´)T, and °dONLNd)£´د) _IntlScript°dONLNd4§¯∞+)M  routines.  °dONLNd@£+ØU)3Forced°dONLNdF§U∞l)* and °dONLNdK£lØù)Default°dONLNdR§ù∞Ù)1 report the actions °dONLNdf§Ù∞˛)Wof°dONLNdi∞<ºÅ(ÿZthese routines.°dONLNdy…<’a*Setting °dONLNdÅ»a‘†)%    FontForce°dONLNdä…†’ )?> to true forces Roman fonts to be interpreted as belonging to °dONLNd»… ’˛(ÒË
  4107. the system°dONLNd”’<·∞(˝ZQscript.  This is for compatibility with applications that hard-code font numbers.°dONLNd%Ì<˘{*    IntlForce°dONLNd.Ó{˙)?  determines the behavior of the °dONLNdNÌ˘U)î
  4108. _IUGetIntl°dONLNdXÓU˙ï)F
  4109.  call.  When °dONLNdeÌï˘‘)@    intlforce°dONLNdnÓ‘˙˛)?
  4110.  is set to°dONLNdy˚<U(#Ztrue, °dONLNd˙Uõ)
  4111. _IUGetIntl°dONLNdâ˚õ)F will return a handle to °dONLNd¢˚≥)m%the international resources (of type °dONLNd«˙≥›)´'itlx'°dONLNdÕ˚›˛)* where°dONLNd‘<C(0Zx°dONLNd’C˙)& is 0-2) for the system script.  When °dONLNd˚˙9)∑    IntlForce°dONLNd9y)? is false, the °dONLNdyø)@
  4112. _IUGetIntl°dONLNdø˛)F
  4113.  will use the°dONLNd+< º(<Zfont of the current port to °dONLNdGº ˛)ÄAdetermine the appropriate resources to fetch.  Thus date formats,°dONLNdâ <,˛(HZ-sorting, etc. can reflect the current script.°dONLNd∑8`Dë+$smPrint°dONLNdø9ÃE“)l4°dONLNd¡9Ej)HPrint action vector°dONLNd’Q<]á(yZGPrint action routine vector; set up at boot time. See M.TE.PrintAction.°dONLNd    i`u≠+$ smSysScript°dONLNd    )jÃv“)l2°dONLNd    +jvÅ)HPreferred system script°dONLNd    Cv`Ç¥(ü~ smLastScript°dONLNd    PwÃÉ“)l2°dONLNd    RwÉt)HLast keyboard script°dONLNd    gÉ`è≠(¨~ smKeyScript°dONLNd    sÑÃê“)l2°dONLNd    uÑê`)HKeyboard script ◊X◊
  4114. (ÏZScript Manager Variables(Ïˇ3) of 10ˇå◊#ˇ ˇˇˇˇ#◊ 
  4115. IR,Times
  4116. .+6-Macintosh Technical Notes /4/˘
  4117. °dONLNd*·*%At boot time and switch-launch time, ,
  4118. Courier°dONLNd%·) )…    SysScript°dONLNd. *?)? and °dONLNd3?)~)    KeyScript°dONLNd<~*Ã)? are set from °dONLNdJÃ*⁄)Nthe°dONLNdN*6W(S6    SysScript°dONLNdW+W7î)? field of the °dONLNde*î6æ)='itlc'°dONLNdk+æ7)* resource if that °dONLNd}+7⁄)P+script is installed and enabled; otherwise,°dONLNd©7CW(`6    SysScript°dONLNd≤8WDn)? and °dONLNd∑7nC≠)    KeyScript°dONLNd¿8≠DO)?# are set to Roman (without setting °dONLNd„7OCÄ)¢Default°dONLNdÍ8ÄDà)1).°dONLNdÌQ]2(y6The °dONLNdÒP2\q)    KeyScript°dONLNd˙Qq]Æ)?  global is °dONLNdQÆ]⁄)=6the current keyboard script, tested and updated by the°dONLNd<]i^(Ü6
  4119. _KeyScript°dONLNdF^^j´)F routine.  When °dONLNdV]´iÒ)M
  4120. _KeyScript°dONLNd`^Òj)F     changes °dONLNdi]i\),    KeyScript°dONLNdr^\jl)?, it °dONLNdw^lj⁄)moves the old value to°dONLNdéjv^(ì6
  4121. LastScript°dONLNdòk^wh)F.  °dONLNdõjhvÆ)
  4122.  
  4123. _KeyScript°dONLNd•kÆwt)F+ can also swap the current key script with °dONLNd–ktw⁄)Δthe last one, which it°dONLNdÁxÑ](†6retrieves from °dONLNdˆw]É£)E
  4124. LastScript°dONLNdx£Ñ¬)F.  The °dONLNdw¬É)    KeyScript°dONLNdxÑZ)? value is also used °dONLNd$xZÑ⁄)Yto get the proper keyboard°dONLNd?Öë≈(≠6'script icon and to retrieve the proper °dONLNdfÑ≈êÔ)≠'KCHR'°dONLNdlÖÔëÛ)*.°dONLNdnù©W(Δ6    SysScript°dONLNdwûW™D)?/ specifies the system script, and is used, for °dONLNd¶ûD™â)Ì example, by °dONLNd≤ùâ©÷)E _FontScript°dONLNdΩû÷™⁄)M,°dONLNdø™∂l(”6 _Font2Script°dONLNdÀ´l∑á)T, and °dONLNd—™á∂‘) _IntlScript°dONLNd‹´‘∑ÿ)M.°dONLNdfi√œW(Ï6    KeyScript°dONLNdÁƒW–_)?, °dONLNdÈ√_œ•)
  4125. LastScript°dONLNdÛƒ•–¬)F, and °dONLNd˘√¬œ)    SysScript°dONLNdƒ–«)?) always contain integers that correspond °dONLNd+ƒ«–⁄)Δto a°dONLNd0–‹i(¯6script number.  °dONLNd@–i‹Ω)Q?Script numbers are documented in The Script Manager chapter of °dONLNd–Ω‹⁄(¯€Inside°dONLNdÜ‹ËI(6    Macintosh°dONLNdè‹IËö)1, Volume V-293.°dONLNdüÙ<t(ZsmSysRef°dONLNd®ı®Æ)l2°dONLNd™ı5)HSystem folder °dONLNd∏Ù5t)E    volRefNum°dONLNd¬u(66Set from the global °dONLNd÷
  4126. u¥)]    BootDrive°dONLNdfl¥h)?' at boot time and switch-launch time.  °dONLNd
  4127. hí)¥SysRef°dONLNd í⁄)* was originally°dONLNd'ˇ(C62a way of testing for vanilla launch versus switch °dONLNdNˇ'P)Álaunch; now the °dONLNd^P&Å)QEnabled°dONLNdeÅ'⁄)1 global is used for°dONLNdy'3V(O6
  4128. that purpose.°dONLNdá?<KÇ+$
  4129. smKeyCache°dONLNdí@®LÆ)l2°dONLNdî@LY)H[Obsolete, do not use]°dONLNd´X<d{(ÅZ    smKeySwap°dONLNdµY®eÆ)l4°dONLNd∑Yeù)H!Keyboard swapping resource handle°dONLNdŸr~.(ö6The °dONLNd›q.}X)'KSWP'°dONLNd„rX~∑)* resource handle is °dONLNd˜r∑~∞)_1put here at boot time and switch-launch time.  A °dONLNd(q∞}⁄)˘'KSWP'°dONLNd/ãÉ(ß6Jresource contains a table of key sequences that will cause the  currently °dONLNdyÉã∞(ß°
  4130. installed °dONLNdÉ~∞ä⁄)-'KCHR'°dONLNdäåò…(¥6#(keyboard mapping table) to change °dONLNd≠å…ò@)±to the preferred system °dONLNd≈ã@ój)w'KCHR'°dONLNdÀåjò⁄)*, switch to the Roman°dONLNd·ò§B(¡6'KCHR'°dONLNdÁôB•”)* , or rotate among the available °dONLNdò”§˝)ë'KCHR'°dONLNd
  4131. ô˝•⁄)*/ resources.  The table includes the virtual key°dONLNd=¶≤ƒ(Œ6!code and the modifier keys.  The °dONLNd^¶ƒ≤)¨following is the °dONLNdo•±D)V'KSWP'°dONLNdu¶D≤⁄)* resource for the Kanji script°dONLNdî≤æh(⁄6interface system.
  4132.     °dONLNd¶ ’Æ*resource 'KSWP' (0, sysheap) {°dONLNdΔ‘<fl¥+$
  4133. {/* array: 3 elements */°dONLNd·fi`Èç+$
  4134.     /* [1] */°dONLNdÌË`Ûs*
  4135. 7Rotate, 49, controlOff, optionOff, shiftOff, commandOn,°dONLNd'Ú`˝ç*
  4136.     /* [2] */°dONLNd3¸`s*
  4137. 7System, 70, controlOff, optionOff, shiftOff, commandOn,°dONLNdm`ç*
  4138.     /* [3] */°dONLNdy`i*
  4139. 5Roman, 66, controlOff, optionOff, shiftOff, commandOn°dONLNd∞<%A(AZ}°dONLNd≤$/"(K6};
  4140. °dONLNdµ;Gë*The resource says rotate °dONLNdŒ:ëFª)y'KCHR'°dONLNd‘;ªG)* resources if a °dONLNd‰;G⁄)I'Space–Command key occurs, switch to the°dONLNd HT=(p6system °dONLNdG=Sg)%'KCHR'°dONLNdHgTe)*0 on  keypad plus (+)–Command key, and switch to °dONLNdIHeTü)˛
  4141. the Roman °dONLNdSGüS…):'KCHR'°dONLNdYH…T⁄)* on°dONLNd]T`¡(|6 keypad asterisk (*)–Command key.°dONLNd~l<xÇ+$
  4142. smGenFlags°dONLNdâm®yÆ)l4°dONLNdãmy/)H
  4143. General flags°dONLNdôÖëÇ(≠6OOnly the two high-order bits are defined (in the file ScriptEqu.a), as follows: ◊4◊˘
  4144. *?4) of 10(ÏìScript Manager Variablesˇ~◊#ˇ ˇˇˇˇ#◊ 
  4145. IR,Times
  4146. .+Z-Developer Support Center(-Û    June 1989 /X/,
  4147. Courier
  4148. °dONLNd)`5–(R~smfShowIcon = 31°dONLNd*6ß)¢#(show icon even if only one script)°dONLNd56`B◊(_~smfDualCaret = 30°dONLNdG7Cª)¢)(use dual caret for mixed direction text)°dONLNdqP<\R(xZThe °dONLNduPR\±)high-order byte of °dONLNdàO±[)_ smgrGenFlags°dONLNdîP\˛)T2, containing these flags, should be setup from the°dONLNd«\<h_(ÖZflags°dONLNdÃ]_ib)# °dONLNdÕ]biô) byte in the °dONLNdŸ\ôh√)7'itlc'°dONLNdfl]√i˛)*C resource.  This is not presently done, but will be fixed in future°dONLNd#i<u—(ëZversions of the Script Manager.°dONLNdCÇ<éT*4The following MPW Pascal procedure demonstrates how °dONLNdwÇTéî(™rto get script °dONLNdÖÅîçæ)@'SICN'°dONLNdãÇæé˛)*
  4149.  resources to°dONLNdôé<öA(∂Z:display even if there is only one script system installed.
  4150.     °dONLNd‘¶<±ñ*PROCEDURE SetSICN;°dONLNdÁ∞<ªK*
  4151. VAR°dONLNdÏ∫`≈ø+$
  4152. SICNstate: Longint;°dONLNdƒ`œó*
  4153. err: Oserr;°dONLNdÿ<„U(ˇZBEGIN°dONLNd‚`Ì+$
  4154. %SICNstate := GetEnvirons(smGenFlags);°dONLNd=Ï`˜Ï*
  4155. BSET(SICNstate,smfShowIcon);°dONLNd]` -*)err := SetEnvirons(smGenFlags,SICNstate);°dONLNdá
  4156. <P(1ZEND;
  4157. °dONLNdå `,¶+$
  4158. smOverride°dONLNdó!Ã-“)l4°dONLNdô!-t)HScript override flags°dONLNdØ9<EJ(aZAt °dONLNd≤9JE˛)\present, this is not set or used by the Script Manager.  It is, however, reserved for future°dONLNdE<QÉ(mZ
  4159. improvements.°dONLNd]`iª+$
  4160. smCharPortion°dONLNd+^Ãj“)l2°dONLNd-^j…)H%Ch vs Sp Extra proportion, 4.12 fixed°dONLNdSv<Ç„(ûZ$This is 16-bit fixed-point value in °dONLNdwv„Dz)ß94.12 format (e.g., 10% = $0199).  It is initialized to 10°dONLNd±Ç<éÜ(™ZCpercent at boot time.  It is intended to be used by script systems °dONLNdÙÇÜé˛(™§to allocate space among°dONLNd é<ös(∂ZBintercharacter spacing and interword spacing when justifying text.°dONLNdO¶<≤ù*A 16-bit fixed-point °dONLNdd¶ù≤˛)aIvalue in 4.12 format is similar to the fixed-point number type defined on°dONLNdÆ≤<æy(⁄Z
  4161. page I-79 of °dONLNdª≤yæ◊)=Inside Macintosh .  °dONLNdœ≤◊æ∂)^1The obvious difference being that  it is only 16 °dONLNd≤∂æ˛)flbits long.  The°dONLNdæ< (ÊZ`integer part of the value is stored in the high four bits, and the fractional part is stored in °dONLNdpæ ˛(Êthe°dONLNdt <÷u(ÚZ low 12 bits.†Ç
  4162. Z(    1\(x    ˇˇˇˇˇˇˇˇ8    1x(î    ˇˇˇˇˇˇˇˇ8    1î(∞    ˇˇˇˇˇˇˇˇ8    1∞(à   ˇˇˇˇˇˇˇˇ8    1Ã(Ë    ˇˇˇˇˇˇˇˇ8    1Ë(    ˇˇˇˇˇˇˇˇ8    1(     ˇˇˇˇˇˇˇˇ8    1 (<    ˇˇˇˇˇˇˇˇ8    1<(X    ˇˇˇˇˇˇˇˇ8    1X(t    ˇˇˇˇˇˇˇˇ8    1t(ê    ˇˇˇˇˇˇˇˇ8    1ê(¨    ˇˇˇˇˇˇˇˇ8    1¨(»    ˇˇˇˇˇˇˇˇ8    1»(‰    ˇˇˇˇˇˇˇˇ8    1‰(    ˇˇˇˇˇˇˇˇ8    1(    ˇˇˇˇˇˇˇˇ8°ñ °ö
  4163. 
  4164. a q
  4165.     '¬'¬°dONLNdˇˇ+ sign
  4166. °dONLNdˇˇ+ bit†ó°ñ °öˇ¸
  4167. û§
  4168. °dONLNdˇˇ(ü2†ó°ñ °öˇ˝
  4169. ∫¿°dONLNdˇˇ(ª1†ó°ñ °öˇ˝
  4170. 
  4171. œ‰°dONLNdˇˇ(◊1†ó°ñ °öˇ˝
  4172. ‘ fi°dONLNdˇˇ*
  4173. 2†ó
  4174. Z("‘ †å°ñ °öˇ¸
  4175. Ú!¯°dONLNdˇˇ+4†ó†å°ñ °öˇ˝
  4176. 
  4177. Ú¯°dONLNdˇˇ(Û1†ó
  4178. Z(" †ç†ç†å†å°ñ °öˇ˝
  4179. 
  4180. °dONLNdˇˇ)1†ó
  4181. Z(" †ç°ñ °öˇ¸
  4182. !°dONLNdˇˇ* 8†ó†ç†å†å°ñ °öˇ˝
  4183. 
  4184. *0°dONLNdˇˇ(+1†ó
  4185. Z("( †ç°ñ °öˇ¸
  4186. '!2°dONLNdˇˇ((16†ó†ç†å†å°ñ °öˇ˝
  4187. 
  4188. FL°dONLNdˇˇ(G1†ó
  4189. Z("D †ç°ñ °öˇ¸
  4190. D!O°dONLNdˇˇ(E32†ó†ç†å†å°ñ °öˇ¸
  4191.     bh°dONLNdˇˇ(c1†ó
  4192. Z("` †ç°ñ °öˇ˝
  4193. _ j°dONLNdˇˇ(`64†ó†ç†å†å°ñ °öˇ¸
  4194.     }ɰdONLNdˇˇ(~1†ó
  4195. Z("{ †ç°ñ °öˇ˝
  4196. y â°dONLNdˇˇ(z128†ó†ç†å†å°ñ °öˇ¸
  4197.     ôü°dONLNdˇˇ(ö1†ó
  4198. Z("ó †ç°ñ °öˇ˝
  4199. ï •°dONLNdˇˇ(ñ256†ó†ç†å°ñ °öˇ¸    
  4200. Ø!√°dONLNdˇˇ+512†ó°ñ °öˇ˝
  4201. 
  4202. ≤Ω°dONLNdˇˇ(µ1†ó
  4203. Z("¥    †ç†å†å°ñ °öˇ˝
  4204. 
  4205. “ÿ°dONLNdˇˇ)1†ó
  4206. Z("– †ç°ñ °öˇ¸
  4207. 
  4208.  !·°dONLNdˇˇ(À1024†ó†ç†å†å°ñ °öˇ¸
  4209.  ÓÙ°dONLNdˇˇ(Ô1†ó
  4210. Z("Ï †ç°ñ °öˇ˝    
  4211. Ê"¸°dONLNdˇˇ(Á2048†ó†ç†å†å°ñ °öˇ˝
  4212. 
  4213.     °dONLNdˇˇ(
  4214. 1†ó
  4215. Z(" †ç°ñ °öˇ¸
  4216. 
  4217. !°dONLNdˇˇ(4096†ó†ç°ñ °öˇ¸
  4218. Åá°dONLNdˇˇ(Ç4†ó†É
  4219. IR
  4220. °dONLNdÅ•!ï+A%(16-bit Fixed-Point Number in 4.12 format
  4221. °dONLNd™9<H•(dZLocal Variables
  4222. °dONLNd∫T<`£*Every script interface °dONLNd—T£`w)g+system has local variables.  Page V-132 of °dONLNd¸Tw`Õ)‘Inside Macintosh °dONLNd
  4223. TÕ`˛)V lists verbs°dONLNd`<l™(àZOwhich are constants that indicate which variable you want to read or set.  The °dONLNdh`™l˛(à»table of constants°dONLNd{l<xU(îZused °dONLNdÄlUx˛)Zto access the local variable, although more accurate than the global table, does contain a°dONLNd€x<Ѱ(†Zfew inaccuracies.  In °dONLNdÒx°Ñ˛)eGaddition four new constants have been added.  Table 2 gives the correct°dONLNd9Ñ<êl(¨Z
  4224. constants. ◊X◊
  4225. *@Script Manager Variables(Ïˇ5) of 10ˇ"◊#ˇ ˇˇˇˇ#◊ 
  4226. IR,Times
  4227. .+6-Macintosh Technical Notes /4/˘
  4228. °dONLNd)<5n+$$Constant°dONLNd    )∫5⁄)~Value°dONLNd)5 )6Meaning TXT®,
  4229. Courier°dONLNd6<B•(_ZsmScriptVersion°dONLNd'7√C…)á0°dONLNd)7CÖ)-Script Interface version number°dONLNdIC<Oû(lZsmScriptMunged°dONLNdXD√P…)á2°dONLNdZDPe)-Local modification count°dONLNdsP<\•(yZsmScriptEnabled°dONLNdÉQ√]…)á4°dONLNdÖQ]M)-Script Enabled Flag°dONLNdô]<ió(ÜZ
  4230. smScriptRight°dONLNdß^√j…)á6°dONLNd©^jD)-Right to Left Flag°dONLNdºj<vê(ìZ smScriptJust°dONLNd…k√w…)á8°dONLNdÀkwA)-Justification Flag°dONLNdfiw<Éû(†ZsmScriptRedraw°dONLNdÌx√Ñœ)á10°dONLNdxÑK)-Word Redraw Flag°dONLNdÑ<ê•(≠ZsmScriptSysFond°dONLNdÖ√ëœ)á12°dONLNdÖë[)-Preferred System Font°dONLNd*ë<ù•(∫ZsmScriptAppFond°dONLNd:í√ûœ)á14°dONLNd=íûn)-Preferred Application Font°dONLNdXû<™û(«ZsmScriptNumber°dONLNdgü√´œ)á16°dONLNdjü´)-Script °dONLNdqû™9)'itl0'°dONLNdwü9´H)* ID°dONLNd{´<∑ê(‘Z smScriptDate°dONLNdà¨√∏œ)á18°dONLNdã¨∏)-Script °dONLNdí´∑9)'itl1'°dONLNdò¨9∏H)* ID°dONLNdú∏<ƒê(·Z smScriptSort°dONLNd©π√≈œ)á20°dONLNd¨π≈)-Script °dONLNd≥∏ƒ9)'itl2'°dONLNdππ9≈H)* ID°dONLNdΩ≈<—ó(ÓZ
  4231. smScriptFlags°dONLNdÀΔ√“œ)á22°dONLNdŒΔ“f)-Script Flags Word (new)°dONLNdÊ“<fió(˚Z
  4232. smScriptToken°dONLNdÙ”√flœ)á24°dONLNd˜“fi)-'itl4'°dONLNd˝”flo)* ID number (new)°dONLNdfl<Îê(Z smScriptRsvd°dONLNd‡√Ïœ)á26°dONLNd‡Ï)-Reserved°dONLNd'Ï<¯ê(Z smScriptLang°dONLNd4Ì√˘œ)á28°dONLNd7Ì˘z)-Script’s language code (new)°dONLNdT˘<•("ZsmScriptNumDate°dONLNdd˙√œ)á30°dONLNdg˙G)- Number/date °dONLNds˙Gâ)Wrepresentation°dONLNdÇ<W(.Zcodes°dONLNdä +¥ (new)°dONLNdê<*ê(GZ smScriptKeys°dONLNdù√+œ)á32°dONLNd†+)-Script °dONLNdß*9)'KCHR'°dONLNd≠9+H)* ID°dONLNd±+<7ê(TZ smScriptIcon°dONLNdæ,√8œ)á34°dONLNd¡,8)-Script °dONLNd»+79)'SICN'°dONLNdŒ,98H)* ID°dONLNd“D<Pó(mZ
  4233. smScriptPrint°dONLNd‡E√Qœ)á36°dONLNd„EQq)-Script printer action routine°dONLNdQ<]ê(zZ smScriptTrap°dONLNdR√^œ)á38°dONLNdR^E)-Trap entry pointer°dONLNd$j<v•(ìZsmScriptCreator°dONLNd4k√wœ)á40°dONLNd7kwA)-Script file creator°dONLNdKw<Éê(†Z smScriptFile°dONLNdXx√Ñœ)á42°dONLNd[xÑ:)-Script file name°dONLNdlÑ<êê(≠Z smScriptName°dONLNdyÖ√ëœ)á44°dONLNd|Öë()- Script name ∞X∞®°dONLNdàûô™X(Δ∑ Table 2–Local Variable Constants°dONLNd©¬ŒN(Í6 Here again °dONLNd¥¬NŒ⁄)6Vthe descriptions are a little terse.  The following section describes each variable in°dONLNd Œ⁄(ˆ64more detail and describes the size of each variable.°dONLNd@Ê@Ú+(    Verb Name°dONLNdJÊ∫Ú⁄)zBytes°dONLNdPÊÚd)HBrief Description°dONLNdb˛<
  4234. •('ZsmScriptVersion°dONLNdrˇ√ …)á4°dONLNdtˇ ó)?Script Interface version number°dONLNdî#(?6OWhen the script interface is loaded, this is set to the current version number.°dONLNd‰/<;û+$smScriptMunged°dONLNdÛ0√<…)á2°dONLNdı0<w)?Local modification count°dONLNdIUŒ(q6'This variable is incremented each time °dONLNd5HŒT)∂
  4235. _SetScript°dONLNd?IUA)F  is called.°dONLNdKa<m•(äZsmScriptEnabled°dONLNd[b√n…)á1°dONLNd]bn_)?Script Enabled Flag°dONLNdq{á$(£6A °dONLNdsz$ÜU) Boolean°dONLNdz{Uáó)1B which indicates whether the script has been enabled.  Set to $FF °dONLNdº{óá⁄(£µ when enabled°dONLNd…áìö(Ø6and zero when not enabled.°dONLNd‰ü<´ó+$
  4236. smScriptRight°dONLNdÚ†√¨…)á1°dONLNdÙ†¨V)?Right to Left Flag ◊4◊˘
  4237. (Ï66) of 10(ÏìScript Manager Variablesˇl◊#ˇ ˇˇˇˇ#◊ 
  4238. IR,Times
  4239. .+Z-Developer Support Center(-Û    June 1989 /X/
  4240. °dONLNd*<6G(RZA ,
  4241. Courier°dONLNd)G5x) Boolean°dONLNd    *x6S)12 indicating if text should be drawn right to left °dONLNd;*S6˛)€'or left to right.  It is set to $FF for°dONLNdc6<B±(^ZRright to left text (Arabic and Hebrew scripts) and zero for left to right (Roman).°dONLNd∂N`Z¥+$ smScriptJust°dONLNd√OÁ[Ì)á1°dONLNd≈O&[w)?Justification Flag°dONLNdÿg<sÓ(èZ%A byte flag which describes how text °dONLNd˝gÓs˛)≤9should be justified.  The possible settings correspond to°dONLNd7s<ı(õZ)the justification flags used by TextEdit.°dONLNdbã`óf+$0°dONLNddãÑó◊)$= left justification°dONLNdzó`£f(ø~1°dONLNd|óÑ£”)$= center justified°dONLNdê£`Øj(À~-1°dONLNdì£ÑØÕ)$= right justified°dONLNd•ª`«¬(‰~smScriptRedraw°dONLNd¥ºÁ»Ì)á1°dONLNd∂º&»Å)?Word Redraw Flag°dONLNd«‘<‡fl(¸ZWA byte flag describing how much of a line should be redrawn when text is being entered.°dONLNd Ï`¯f+$0°dONLNd"ÏѯÎ)$Only draw a character°dONLNd9¯`f( ~1°dONLNd;¯ÑÛ)$Redraw the entire word°dONLNdS`j(,~-1°dONLNdVÑ)$Redraw the entire line (Arabic)°dONLNdv`(…(E~smScriptSysFond°dONLNdÜÁ)Ì)á2°dONLNdà&)ë)?Preferred System Font°dONLNdû5<AÍ(]ZThis is the font family ID for °dONLNdΩ5ÍA˛)Æ.the preferred System Font.  In a Roman system,°dONLNdÏA<Mó(jZ
  4242. ScriptSysFond°dONLNd˘BóN/)[! is 0, the family ID for Chicago.°dONLNdZ`f…(É~smScriptAppFond°dONLNd+[ÁgÌ)á2°dONLNd-[&g§)?Preferred Application Font°dONLNdHt<Ä’(úZ!Font family ID for the preferred °dONLNdit’Äó)ô&Application Font.  In a Roman system, °dONLNdèsóÚ)¬
  4243. ScriptAppFond°dONLNdútÚIJ)[ is°dONLNd†Ä<å√(®Z3, the family ID for Geneva.°dONLNdΩò`§±+$smScriptNumber°dONLNdÃòÁ§Ì)á4°dONLNdŒò&§k)?Script 'itl0' ID°dONLNdfl±<Ωä(ŸZResource ID of °dONLNdÓ∞亥)N'itl0'°dONLNdÙ±¥Ω)* for this script.  The °dONLNd ∞ºE)g'itl0'°dONLNd±EΩ•)* resource describes °dONLNd%±•Ω˛)`how numbers and°dONLNd5Ω<…Ø(ÂZMtimes should be displayed.  The resource ID should match the country version °dONLNdÇΩØ…˛(ÂÕcode for a given°dONLNdì…<’d(ÒZcountry.°dONLNdú·`Ìü+$ smScriptDate°dONLNd©·ÁÌÌ)á4°dONLNd´·&Ìk)?Script 'itl1' ID°dONLNdº˙<†("ZResource ID of the °dONLNdœ˘† )d'itl1'°dONLNd’˙ 7)* for this script.  The °dONLNdÏ˘7a)m'itl1'°dONLNdÚ˙aÛ)* describes how dates should °dONLNd˙Û˛)íbe°dONLNd<m(.Z
  4244. displayed.°dONLNd`*û+$ smScriptSort°dONLNd)Á*Ì)á4°dONLNd+&*k)?Script 'itl2' ID°dONLNd<7<Cz(_Z Resource ID °dONLNdH7zCö)>of the °dONLNdO6öBƒ) 'itl2'°dONLNdU7ƒC+)* for this script.  The °dONLNdl6+BU)g'itl2'°dONLNdr7UC˛)*$ contains routines for sorting.  See°dONLNdóC<O±(kZM.TE.NewStringComp.°dONLNd´[`gª+$
  4245. smScriptFlags°dONLNdπ\ÁhÌ)á2°dONLNdª\&h\)? Script flags°dONLNd»t<Ä(úZ(This verb provides access to the script °dONLNdtIJ)≈2flags word, which contains bit flags that describe°dONLNd#Å<ç¶(©Zfeatures of the script.  °dONLNd<Ŷçm)j+This word is initialized from the script’s °dONLNdgÄmåó)«'itlb'°dONLNdmÅóç˛)* resource.  Constants°dONLNdÉç<ô0(µZ4specifying the bit numbers are described in Table 3. ◊X◊
  4246. *7Script Manager Variables(Ïˇ7) of 10ˇ¥◊#ˇ ˇˇˇˇ#◊ 
  4247. IR,Times
  4248. .+6-Macintosh Technical Notes /4/˘
  4249. °dONLNd¨)Ω+îBit°dONLNd).5`(QLConstant°dONLNd
  4250. )ü5Ã)qNumber°dONLNd)51)Q Description TJT‚,
  4251. Courier°dONLNd 6.BÇ(_L smsfIntellCP°dONLNd-7±C∑)É0°dONLNd/7Cé)?$script has intelligent cut and paste°dONLNdTC.OÇ(lL smsfSingByte°dONLNdaD±P∑)É1°dONLNdcDPp)?script has only single bytes°dONLNdÄP.\{(yL smsfNatCase°dONLNdåQ±]∑)É2°dONLNdéQ]æ)?+native characters have upper and lower case°dONLNd∫].i{(ÜL smsfContext°dONLNdΔ^±j∑)É3°dONLNd»^jî)?#contextual script (e.g., AIS-based)°dONLNdÏj.vó(ìLsmsfNoForceFont°dONLNd¸k±w∑)É4°dONLNd˛kwa)?will not force characters°dONLNdw.ÉÇ(†L smsfB0Digits°dONLNd%x±Ñ∑)É5°dONLNd'xÑ)?has alternative digits in B0-B9°dONLNdGÑ.êm(≠L    smsfForms°dONLNdQÖ±ëΩ)É13°dONLNdTÖëá)?!uses contextual forms for letters°dONLNdvë.ùâ(∫L
  4252. smsfLigatures°dONLNdÑí±ûΩ)É14°dONLNdáíûc)?uses contextual ligatures°dONLNd°û.™{(«L smsfReverse°dONLNd≠ü±´Ω)É15°dONLNd∞ü´z)? reverses native text, right-left  J ‚°dONLNd—∏°ƒP(‡øTable 3–Constant Bit Numbers°dONLNdÓ–<‹Ñ(¯Z
  4253. smScriptToken°dONLNd¸–√‹…)á2°dONLNd˛–‹G)?Script 'itl2' ID°dONLNdÈıc(6Resource ID of °dONLNdÈcıu)Kthe °dONLNd"ËuÙü)'itl4'°dONLNd(Èüı)* for this script.  The °dONLNd?ËÙ0)g'itl4'°dONLNdEÈ0ı⁄)*# contains contains tables needed by°dONLNdiˆ(66the number formatting and conversion routines and the °dONLNdüıx(;
  4254. _intlTokenize°dONLNd¨ˆx⁄)[ routine.  See Script°dONLNd¬©(*6Manager 2.0, Interim Chapter.°dONLNd‡<&+$ smScriptRsvd°dONLNdÌ√&…)á4°dONLNdÔ&.)?Reserved°dONLNd¯2<>~(ZZ smScriptLang°dONLNd2√>…)á2°dONLNd2>m)?Script’s language code°dONLNdJVÔ(r6)This verb accesses a word which contains °dONLNdGJÔV⁄)◊.the current language code for the script.  The°dONLNdvVb(~66language codes are defined in the MPW interface files.°dONLNd≠n<z•+$smScriptNumDate°dONLNdΩo√{…)á2°dONLNdøo{∂)?$Number and date representation codes°dONLNd‰áì{(Ø6This verb accesses a °dONLNd˘á{ì⁄)cHword containing the number and date representation codes for the script.°dONLNdCìül(ª6HThe number representation code is in the high byte of the word, and the °dONLNdãìlü⁄(ªädate code is in the low°dONLNd£ü´0(«6byte.°dONLNd©∑√*3The possible values for number representations and °dONLNd‹∑√⁄)ˆ+date codes are declared as constants in the°dONLNd√œz(Î6MPW interface files.°dONLNd€`ÁÀ+HThe number codes are:°dONLNd3€ÁZ)êand the date codes are:°dONLNdKÛ`ˇ©(~intWestern = 0;°dONLNd\ÛˇC)êcalGregorian = 0;°dONLNdnˇ` °('~intArabic = 1;°dONLNdˇ I)êcalArabicCivil = 1;°dONLNdì `§(3~
  4255. intRoman = 2;°dONLNd¢ N)êcalArabicLunar = 2;°dONLNd∂`#¨(?~intJapanese = 3;°dONLNd»#=)êcalJapanese = 3;°dONLNdŸ#`/Ø(K~intEuropean = 4;°dONLNdÎ#/4)êcalJewish = 4;°dONLNd˛/;2* calCoptic = 5;°dONLNd
  4256. G<S(oZ smScriptKeys°dONLNdG√S…)á4°dONLNdGSZ)?Script 'KCHR' ID°dONLNd-_kh(á6BResource ID of preferred 'KCHR' resource.  The 'KCHR' resource is °dONLNdo_hk⁄(áÜused to map virtual key°dONLNdákwC(ì6<codes into the correct character code.  See M.TB.KeyMapping.°dONLNdƒÉ<è{+$ smScriptIcon°dONLNd—É√è…)á4°dONLNd”ÉèT)?Script 'SICN' ID ◊4◊˘
  4257. (Ï68) of 10(ÏìScript Manager Variablesˇf◊#ˇ ˇˇˇˇ#◊ 
  4258. IR,Times
  4259. .+Z-Developer Support Center(-Û    June 1989 /X/
  4260. °dONLNd<)†(EZResource ID of the °dONLNd†)˛)dEsmall icon that is used to represent which country specific resources°dONLNdY*<6@(RZ(,
  4261. Courier°dONLNdZ)@5j)'itl0'°dONLNd`*j6q)*, °dONLNdb)q5õ)'itl1'°dONLNdh*õ6¢)*, °dONLNdj)¢5Ã)'itl2'°dONLNdp*Ã6”)*, °dONLNdr)”5˝)'KCHR'°dONLNdx*˝6˛)*8) are currently installed in the system.  Presently, the°dONLNd±7<CÖ(_Z
  4262. Roman system °dONLNdæ7ÖCÍ)Idoes not display the °dONLNd”6ÍB)e'SICN'°dONLNdŸ7C˛)*/.  Arabic, Kanji, Chinese, and Hebrew interface°dONLNd    C<Oà(kZGsystems do display this icon in the upper-right corner of the menu bar.°dONLNdQ[`gª+$
  4263. smScriptPrint°dONLNd_\ÁhÌ)á4°dONLNda\&hß)?Script printer action routine°dONLNdÄt<Ät(úZ<Print action routine vector; setup when script is installed °dONLNdºttIJ(úíby Script Manager.  See°dONLNd‘Ä<åñ(®ZM.TE.PrintAction.°dONLNdÊò`§¥+$ smScriptTrap°dONLNdÛôÁ•Ì)á4°dONLNdıô&•{)?Trap entry pointer°dONLNd±<Ω(ŸZ,Pointer to Script dispatch routine.  Script °dONLNd4±Ω˛)“,Manager routines always belong to one of two°dONLNdaΩ<…Ÿ(ÂZRgroups.  The first group of routines are common to every script interface system, °dONLNd≥ΩŸ…˛(˜and the°dONLNdª…<’(ÒZ,second group must be supplied by the script °dONLNdÁ…’˛)€0interface system.  This variable will point to a°dONLNd÷<‚z(˛ZEdispatch routine for the interface-supplied routines.  When you call °dONLNd]’z·«(˛ò _ScriptUtil°dONLNdh÷«‚Œ)M, °dONLNdj÷Œ‚˛) it looks at°dONLNdv‚<Ó(
  4264. Z/the selector that is passed and either calls a °dONLNd•‚Ó˛)À1common routine or calls the routine whose address°dONLNd◊Ô<˚y(Z
  4265. is stored in °dONLNd‰Óy˙ø)=
  4266. ScriptTrap°dONLNdÓÔø˚)F.  The routine in °dONLNdÓ˙l)Y smScriptTrap°dONLNd Ôl˚°)T  will then °dONLNdÔ°˚˛)5use the selector to°dONLNd+˚<™(#ZRvector to the correct routine.  In general, routines that display or measure text °dONLNd}˚™˛(#»in some way will°dONLNdé<¡(/Zbe supplied by the interface.°dONLNd¨<+X*A list °dONLNd≥X+˛)Vat the end of this Note indicates which routines are implemented by the Script Manager°dONLNd
  4267. +<7Y(SZ=and which routines are supplied by a script interface system.°dONLNdHC`O…+$smScriptCreator°dONLNdXDÁPÌ)á4°dONLNdZD&Pw)?Script file creator°dONLNdn\<hÊ(ÑZ$The four character creator type for °dONLNdí\Êh˛)™9the script interface’s file.  For Roman it is “ZSYS,” the°dONLNdÃh<tÂ(êZ$same creator as any system file has.°dONLNdÒÄ`å¥+$ smScriptFile°dONLNd˛ÅÁçÌ)á4°dONLNdÅ&çp)?Script file name°dONLNdô<•›(¡Z!A pointer to the a Pascal string °dONLNd2ô›•˛)°9which contains the name of the file containing the script°dONLNdl•<±0(ÕZ3interface system.  For the Roman SIS, it is System.°dONLNd†Ω`…¥+$ smScriptName°dONLNd≠æÁ Û)á44°dONLNd∞æ& ^)? Script name°dONLNdº÷<‚+(˛Z0A pointer to a Pascal string which contains the °dONLNdÏ÷+‚˛)Ô)script interface’s name.  For Roman it is°dONLNd‚<Óú(
  4268. Znaturally, “Roman.”
  4269. °dONLNd*<≠*'Who Does What?
  4270. °dONLNd9!<-÷*Table 4 breaks the documented °dONLNdW!÷-˛)ö:routines into common Script Manager routines and interface°dONLNdí-<9ç(UZspecific routines. ◊X◊
  4271. *óScript Manager Variables(Ïˇ9) of 10ˇD◊#ˇ ˇˇˇˇ#◊ 
  4272. IR,Times
  4273. .+6-Macintosh Technical Notes /4/˘
  4274. °dONLNd)`5»+H$Common Routines°dONLNd)5X)êInterface Supplied T|TÑ,
  4275. Courier°dONLNd#6`B≠(_~ _FontScript°dONLNd/6B/)ê    _CharByte°dONLNd9B`N≠(k~ _IntlScript°dONLNdEBN/)ê    _CharType°dONLNdON`Z¶(w~
  4276. _KeyScript°dONLNdZNZ=)ê _Pixel2Char°dONLNdfZ`f¥(É~ _GetEnvirons°dONLNdsZf=)ê _Char2Pixel°dONLNdf`r¥(è~ _SetEnvirons°dONLNdåfrR)ê_Transliterate°dONLNdõr`~¥(õ~ _Font2Script°dONLNd®r~/)ê    _FindWord°dONLNd≤~`ä≠(ß~ _Format2Str°dONLNdæ~ä=)ê _HiliteText°dONLNd ä`ñ¥(≥~ _FormatStr2X°dONLNd◊äñ/)ê    _DrawJust°dONLNd·ñ`¢≠(ø~ _FormaX2Str°dONLNdÌñ¢D)ê _MeasureJust°dONLNd˙¢`Æ…(À~_GetFormatOrder°dONLNd
  4277. ¢Æ=)ê _ParseTable°dONLNdÆ`∫¬(◊~_InitDateCache°dONLNd%Æ∫R)ê_VisibleLength°dONLNd4∫`Δª(„~
  4278. _IntlTokenize°dONLNdB∫ΔR)ê_FindScriptRun°dONLNdQΔ`“¬(Ô~_LongDate2Secs°dONLNd`Δ“D)ê _PortionText°dONLNdm“`fi¬(˚~_LongSecs2Date°dONLNd|fi`Í≠* _Str2Format°dONLNdàÍ`ˆ¥* _String2Date°dONLNdïˆ`¥* _String2Time°dONLNd¢`–* _StyledLineBreak°dONLNd≥`≠* _ToggleDate°dONLNdø`&g*   E|EѰdONLNd¡3??≤([]?Table 4–Script Manager Routines and Interface Specific Routines°dONLNdWc^(Ä6
  4279. _GetScript°dONLNd X^d{)F and °dONLNdW{c¡)
  4280. _SetScript°dONLNdX¡dH)F, which return the values °dONLNd4XHd⁄)áof local script variables, are°dONLNdSdpœ(å6\implemented by the Script Manager for some verbs and the script interface system for others.°dONLNd∞}âN*AThere is also a group of Script Manager routines which don’t use °dONLNdÒ}Nâ`(•lthe °dONLNdı|`à≠) _ScriptUtil°dONLNd}≠â⁄)M
  4281.  trap, but°dONLNd âït(±6are documented in °dONLNdâtï)\The Script Manager chapter of °dONLNd;âïc)úInside Macintosh°dONLNdKâcï⁄)S, Volume V-293 or The°dONLNdaï°Ô(Ω6+Script Manager 2.0 Interim Chapter.  There °dONLNdåïÔ°÷)◊1routines are utilities that read and write to low°dONLNdΩï÷°⁄)Á-°dONLNdæ°≠K(…6<memory or PRAM.  It is important to use these routines when °dONLNd˙°K≠⁄(…ithey are available.  That will°dONLNd≠πS(’6Callow Apple to modify where global variables, etc. are stored, and °dONLNd\≠Sπ⁄(’qyour application will remain°dONLNdyπ≈†(·6compatible.  The utilities are:°dONLNdö—<›û+$GetDefFontSize°dONLNd™›<ÈÇ*
  4282. GetSysFont°dONLNd∂È<ıÇ*
  4283. GetAppFont°dONLNd¬ı<ó*
  4284. GetMBarHeight°dONLNd—<
  4285. Ç*
  4286. GetSysJust°dONLNd›
  4287. <Ç*
  4288. SetSysJust°dONLNdÈ<%ó*
  4289. ReadLocation °dONLNdˆó&1)[(documented in Interim Chapter)°dONLNd&<2û(OZWriteLocation °dONLNd%'û38)b(documented in Interim Chapter)°dONLNdEWcÇ(6Further Reference: Ç4Ǣ°dONLNdXd*p.+
  4290. •°dONLNdZd<pç)Inside Macintosh°dONLNdjdçp>)Q", Volume V-293, The Script Manager°dONLNdçp*|.(òH•°dONLNdèp<|õ)M.TB.KeyMapping°dONLNdü|*à.(§H•°dONLNd°|<àí)M.TE.PrintAction ◊4◊˘
  4291. (Ï610)
  4292.  of 10(ÏìScript Manager Variablesˇ‘◊#ˇ ˇˇˇˇ#◊†Ç 
  4293. /ZÅ#
  4294.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4295. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4296. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4297. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4298. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4299.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4300. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  4301. IR.°dONLNdz<çü(ßZ(Modifying the Standard String Comparison
  4302. °dONLNd)å<õZ*Text°dONLNd/ågõ˛(∑ÖM.TE.NewStringComp
  4303. °dONLNdBß<≥t(œZ Revised by:°dONLNdOß≈≥˛(œ„
  4304. March 1988°dONLNdZ≥<øq(€Z Written by:°dONLNdf≥Ñøª)H
  4305. Mark Davis°dONLNdsøÑÀÏ* Priscilla Oppenheimer°dONLNdâø±À˛(Áœ
  4306. November 1987°dONLNdó◊<„K(ˇZ9This technical note describes how to modify the standard °dONLNd–◊K„˛(ˇi$string comparison by constructing an,
  4307. Courier°dONLNdı„<ÔX( Zitl2°dONLNd˘‰X\) °dONLNd˙‰\˛)Qresource. Developers may want to modify the standard string comparison if Apple’s°dONLNdL<¸ê(ZIcomparison doesn’t meet their needs or if Apple has not written a string °dONLNdïê¸˛(Æcomparison routine for°dONLNd¨¸<÷($Z the language that concerns them. 3X3
  4308. °dONLNdÕ-<<≥*4General Structure
  4309. °dONLNdflI<UQ*The °dONLNd„HQTm)itl2°dONLNdÁImU≈) resource contains °dONLNd˙I≈U˛)X?a number of procedures that are used for accurate comparison of°dONLNd:U<aE(}Z6text by the International Utilities Package. Refer to °dONLNdpUEaö(}cInside Macintosh°dONLNdÄUöa˛)U, volume V for an°dONLNdíb<n(äZ/explanation of the algorithm used. The default °dONLNd¡am4)‹itl2°dONLNd≈b4n˛)) for standard English text, which does no°dONLNdÔn<z(ñZ+special processing, has the following form:
  4310.     °dONLNdÜ`ë+$ ; normal Include/Load statements°dONLNd>ê`õ*
  4311. &Include 'hd:mpw:aincludes:ScriptEqu.a'°dONLNdfö`•y*
  4312. Print°dONLNdlöÑ•±)$    On,NoMDir°dONLNdwÆ`π~(’~String°dONLNd~ÆÑπò)$AsIs°dONLNdɬ<Õ©(ÈZI;------------------------------------------------------------------------°dONLNdÕÃ<◊F*
  4313. ; °dONLNd–Ã`◊()$(dispatch table at the front of the code.°dONLNd˘÷<·©(˝ZI;------------------------------------------------------------------------°dONLNdC‡<ÎU*
  4314. Intl1°dONLNdJ‡ÑÎò)HProc°dONLNdPÍ`ıt(~With°dONLNdUÍÑıÌ)$IUSortFrame,IUStrData°dONLNdkÙ<ˇx(Z HookDispatch°dONLNdy˛`    t+$
  4315. dc.w°dONLNd~˛Ñ    Ì)$ReturnEQ-HookDispatch°dONLNd   Z)ê; InitProc = 0°dONLNd§`t(/~dc.w°dONLNd©ÑÌ)$ReturnEQ-HookDispatch°dONLNdø_)ê; FetchHook = 2°dONLNd–`t(9~dc.w°dONLNd’ÑÌ)$ReturnEQ-HookDispatch°dONLNdÎi)ê; VernierHook = 4°dONLNd˛`'t(C~dc.w°dONLNdÑ'Ì)$ReturnEQ-HookDispatch°dONLNd'i)ê; ProjectHook = 6°dONLNd,&`1t(M~dc.w°dONLNd1&Ñ1Ì)$ReturnEQ-HookDispatch°dONLNdG&1s)ê; ReservedHook1 = 8°dONLNd\0`;t(W~dc.w°dONLNda0Ñ;Ì)$ReturnEQ-HookDispatch°dONLNdw0;x)ê; ReservedHook2 = 10°dONLNdåD<O©(kZI;------------------------------------------------------------------------°dONLNd÷N<Yπ*
  4316. ; Some common exit points°dONLNdX<c©*
  4317. I;------------------------------------------------------------------------°dONLNd:b<md*
  4318. ReturnNE°dONLNdEl`w~+$
  4319. tst.w °dONLNdLlÑw¨)$MinusOne°dONLNdVlw')l ; set cc NE°dONLNdcv`Åo(ù~rts°dONLNdgÄ<ãd(ßZReturnEQ°dONLNdqä`ïy+$
  4320. cmp.w°dONLNdwäÑïù)$d0,d0°dONLNd~äÃï)H ; set cc EQ°dONLNdãî`üo(ª~rts°dONLNdèû<©©(≈ZI;------------------------------------------------------------------------ ◊X◊
  4321. *'(Modifying the Standard String Comparison(Ï1) of 8ˇ°¿Ù%%DSIDICT:_cv
  4322. currentdict /bu known {bu}if
  4323. userdict /_cv known not{userdict /_cv 30 dict put}if
  4324. _cv begin
  4325. /bdf{bind def}bind def
  4326. currentscreen/cs exch def/ca exch def/cf exch def
  4327. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4328. /ss{//cf //ca //cs setscreen}bdf
  4329. /stg{ss setgray}bdf
  4330. /strgb{ss setrgbcolor}bdf
  4331. /stcmyk{ss cvcmyk}bdf
  4332. /min1{dup 0 eq{pop 1}if}bdf
  4333. end
  4334. currentdict /bn known {bn}if
  4335. †ø◊#ˇ ˇˇˇˇ#◊ 
  4336. IR,Times
  4337. .+6-Macintosh Technical Notes /4/˘,
  4338. Courier
  4339.     °dONLNd<(_+$EndWith°dONLNd    '<2_*
  4340. EndWith°dONLNd1<<K*
  4341. End
  4342. °dONLNdGSó(o6PIf modifications need to be made to the comparison process, then one or more of °dONLNdfGóS⁄(oµthe dispatches°dONLNduS_Ô({60will be modified to point to different routines:
  4343. °dONLNdßk<wT+$dc.w°dONLNd¨k`wfi)$InitProc-HookDispatch°dONLNd¬kwD)ê; InitProc = 0°dONLNd“v<ÇT(ûZdc.w°dONLNd◊v`lj)$FetchProc-HookDispatch°dONLNdÓvÇJ)ê; FetchHook = 2°dONLNdˇÅ<çT(©Zdc.w°dONLNdÅ`ç)$VernierProc-HookDispatch°dONLNdÅçz)¥; VernierHook = 4°dONLNd0å<òT(¥Zdc.w°dONLNd5å`ò)$ProjectProc-HookDispatch°dONLNdNåòz)¥; ProjectHook = 6
  4344. °dONLNd`£Ø (À64There are a number of different changes that can be °dONLNdî£ Ø⁄)Ù(made to the comparison routines. Some of°dONLNdΩØªΩ(◊6!the common modifications include:°dONLNdfl«”.*  1.°dONLNd‰«<”)$$Comparing two bytes as one character°dONLNd
  4345. ”<fl* 'Yugoslavian “l” < “lj” < “m”; Japanese…°dONLNd2”fly)ÿ[InitProc, FetchProc]°dONLNdHflÎ.(6  2.°dONLNdMfl<Έ)$'Comparing characters in different order°dONLNdvÎ<˜ü* Norwegian “z” < “å”°dONLNdçΘS)ÿ
  4346. [ProjectProc]°dONLNdõ˜.(6  3.°dONLNd†˜<‘)$Comparing one character as two°dONLNd¿<ï* German “ä” ≈ “ae”°dONLNd’S)ÿ
  4347. [ProjectProc]°dONLNd„.(76  4.°dONLNdË<<)$7Ignoring characters unless strings are otherwise equal:°dONLNd!<'* )“blackbird” < “black-bird” < “blackbirds”°dONLNdK'S)ÿ
  4348. [ProjectProc]°dONLNdY'3.(O6  5.°dONLNd^'<3Ÿ)$Changing the secondary ordering°dONLNd3<?≠* Bibliographic “a” < “A”°dONLNdô3?U)ÿ
  4349. [VernierProc]°dONLNdßKW≠(s6OThe comparison hook procedures are all assembly language based, with arguments °dONLNdˆK≠W⁄(sÀ    described°dONLNdWcÔ(6-below. Since the routines may be called once °dONLNd-WÔc⁄)◊2per character in both strings, the routines should°dONLNd`co(ã6be as fast as possible.°dONLNdx{áÄ*The condition codes °dONLNdå{Äá⁄)hDare used to return information about the status of the hook routine.°dONLNd—àîb(∞6ETypically the normal processing of characters will be skipped if the °dONLNdábìw(∞ÄCCR°dONLNdàwî•)  is set to °dONLNd$á•ì≥).NE°dONLNd&à≥î⁄), so the°dONLNd/ï°∫(Ω6"default return should always have °dONLNdQî∫†»)¢EQ°dONLNdSï»°fl) set. °dONLNdYïfl°⁄)4Each of these routines has access to the stack frame°dONLNdé°≠4( 6(A6)°dONLNdí¢4Æ^)> used in the comparison routine, which has the following form:
  4350.     °dONLNd—∫≈O(·6 IUSortFrame°dONLNd›∫`≈~)HRecord°dONLNd‰∫Ñ≈Ÿ)${oldA6},Decrement°dONLNdˆƒœ6(Î6result°dONLNd˝ƒ<œP)$ds.w°dONLNdƒ`œe)$1°dONLNdŒŸ6(ı6argTop°dONLNd Œ<ŸK)$equ°dONLNdŒ`Ÿe)$*°dONLNdÿ„@(ˇ6aStrText°dONLNdÿ`„t)Hds.l°dONLNdÿÑ„â)$1°dONLNd!‚Ì@(    6bStrText°dONLNd*‚`Ìt)Hds.l°dONLNd/‚ÑÌâ)$1°dONLNd1Ϙ;(6aStrLen°dONLNd9Ï`˜t)Hds.w°dONLNd>Ïјâ)$1°dONLNd@ˆ;(6bStrLen°dONLNdHˆ`t)Hds.w°dONLNdMˆÑâ)$1°dONLNdO ;('6argSize°dONLNdW` o)Hequ°dONLNd[Ñ ¨)$argTop-*°dONLNdd
  4351. 6(16return°dONLNdk
  4352. <P)$ds.l°dONLNdp
  4353. `e)$1°dONLNdr1(;6oldA6°dONLNdy`t)Hds.l°dONLNd~Ñâ)$1°dONLNdÄ)1(E6aInfo°dONLNdá`)j)Hds°dONLNdäÑ)±)$    IUStrData°dONLNdî(31(O6bInfo°dONLNdõ(`3j)Hds°dONLNdû(Ñ3±)$    IUStrData°dONLNd®2=@(Y6wantMag °dONLNd±2`=t)Hds.b°dONLNd∂2Ñ=â)$1°dONLNd∏2®=/)$ 1-MagStrig 0-MagIdString.°dONLNd‘<G6(c6weakEq°dONLNd€<<GP)$ds.b°dONLNd‡<`Ge)$1°dONLNd„<®GC)H; Signals at most weak equality°dONLNdFQ6(m6msLock°dONLNd
  4354. F<QP)$ds.b°dONLNdF`Qe)$1°dONLNdF®Q*)H; high byte of master ptr.°dONLNd-P[@(w6weakMag °dONLNd6P`[t)Hds.b°dONLNd;PÑ[â)$1°dONLNd=P®[/)$ -1 weak, 1 strong compare°dONLNdYZeJ(Å6
  4355. supStorage°dONLNddZ`et)Hds.b°dONLNdiZÑeé)$18°dONLNdlZ®e¯)$; extra storage.°dONLNd}doE(ã6    localSize°dONLNdád`oo)Hequ°dONLNdãdÑoâ)$*°dONLNdçd®oÈ)$
  4356. ; frame size.°dONLNdùn`yt(ï~EndR
  4357. °dONLNd¢Ñê8(¨6There °dONLNd®Ñ8ê⁄) Uare three fields in this frame that are of interest for altering text comparison. The°dONLNd˛êú^(π6
  4358. supStorage°dONLNdë^ùQ)F5 field is an area reserved for use by the comparison °dONLNd=ëQù⁄)Ûhook procedures as they see°dONLNdYû™>(Δ6    fit. The °dONLNdbù>©a)&aInfo°dONLNdgûa™x)# and °dONLNdlùx©õ)bInfo°dONLNdqûõ™#)# records contain information °dONLNdéû#™⁄)à'about the current byte positions in the ◊4◊˘
  4359. (Ï62) of 8(ÏK(Modifying the Standard String Comparisonˇ◊#ˇ ˇˇˇˇ#◊ 
  4360. IR,Times
  4361. .+Z-Developer Support Center(-Ï
  4362. March 1988 /X/
  4363. °dONLNd<)”(EZtwo compared strings A and B, °dONLNd”)˛)ó?and information about the status of current characters in those°dONLNd^*<6s(RZ string. The ,
  4364. Courier°dONLNdj)s5≤)7    IUStrData°dONLNds*≤6E)? record has the following form:
  4365.     °dONLNdìE<Pi(lZ    IUStrData°dONLNdùEÑP¢)HRecord°dONLNd•EÃP—)H0°dONLNdßO<Z_(vZcurChar°dONLNdØOÑZò)Hds.w°dONLNdµOÃZ—)H1°dONLNd∑OZT)$; current character.°dONLNdÃY<dd(ÄZmapChar °dONLNd’YÑdò)Hds.w°dONLNd€YÃd—)H1°dONLNd›Yd^)$; projected character.°dONLNdÙc<nd(äZdecChar °dONLNd˝cÑnò)Hds.w°dONLNdcÃn—)H1°dONLNdcnï)$!; decision char for weak equality°dONLNd'm<xd(îZbufChar °dONLNd0mÑxò)Hds.b°dONLNd6mÃx—)H1°dONLNd8mxc)$; buffer for expansion.°dONLNdPw<Çi(ûZ    justAfter°dONLNdZwÑÇò)Hds.b°dONLNd`wÃÇ—)H1°dONLNdbwÇê)$ ; boolean for AE vs ligature-AE.°dONLNdÉÅ<å_(®ZignChar°dONLNdãÅÑåò)Hds.b°dONLNdëÅÃå—)H1°dONLNdìÅåT)$; flag: ignore char.°dONLNd®ã<ñ_(≤ZnoFetch°dONLNd∞ãÑñò)Hds.b°dONLNd∂ãÃñ—)H1°dONLNd∏ãñm)$; flag: no fetch of next.°dONLNd“ï<†Z(ºZstrCnt°dONLNdŸï`†t)$ds.w°dONLNd‡ïÆ—)l1°dONLNd‚ï†6)$; length word.°dONLNdÒü<™Z(ΔZstrPtr°dONLNd¯ü`™t)$ds.l°dONLNdˇüÙ—)l1°dONLNdü™h)$; current ptr to string.°dONLNd©Ñ¥ò(–¢EndR
  4366. °dONLNd!À<⁄ª(ˆZThe Init Procedure
  4367. °dONLNd4Ê<Ú∫*RThe Init Procedure is used to initialize the comparison process. The main use for °dONLNdÜÊ∫Ú˛(ÿthis procedure°dONLNdïÚ<˛π(Zis for double-byte scripts. °dONLNd±Úπ˛˛)}GAs an optimization, the International Utilities will perform an initial°dONLNd˘˛<
  4368. Ü(&ZFcheck on the two strings, comparing for simple byte-to-byte equality. °dONLNd?˛Ü
  4369. ˛(&§Thus any common initial°dONLNdW
  4370. <„(2Z\substrings are checked before the Init procedure is called. The string pointers and lengths °dONLNd≥
  4371. „˛(2in the°dONLNd∫<"{(?Z    IUStrData°dONLNd√{#¡)?D records have been updated to point just past the common substrings.°dONLNd/<;c(WZ5Languages such as Japanese or Yugoslavian, which may °dONLNd=/c;˛(WÅconsider two bytes to be one°dONLNdZ;<GQ(cZ8character, may have to back up one byte, as shown below.
  4372.     °dONLNdìS<^©*I;------------------------------------------------------------------------°dONLNd›]<hi*
  4373.     ; Routine°dONLNdÁ]Ñh¨)HInitProc°dONLNdg<r_(éZ; Input°dONLNd¯gÑr˜)HA6          Local Frame°dONLNdq<|d(òZ; Output°dONLNdqÑ|É)H3CCR         NE to skip entire sort (usually set EQ)°dONLNdM{<Üi(¢Z    ; Trashes°dONLNdW{ÑÜ )HStandard regs:°dONLNdf{Ü')l A0/A1/D0-D2°dONLNdrÖ<ên(¨Z
  4374. ; Function°dONLNd}ÖÑê[)H+Initialize any special international hooks.°dONLNd©è<öA(∂Z;°dONLNd¨èÑöÉ)H3Double-byte scripts must synchronize AInfo.StrPtr &°dONLNd‡ô<§ı(¿Z%;                  BInfo.StrPtr here!°dONLNd£<Æ©*
  4375. I;------------------------------------------------------------------------°dONLNdP≠<∏ü*
  4376. G; Note: this should also check for single-byte nigori or maru, as below°dONLNdò¬<Õd*InitProc°dONLNd¢Ã`◊~+$
  4377. move.w°dONLNd©ÃÑ◊œ)$AStrLen(a6), d0°dONLNdπÃ◊")l
  4378. ; A length°dONLNd≈÷`·y(˝~sub.w°dONLNdÀ÷Ñ·„)$AInfo.StrCnt(a6),d0°dONLNdfl÷·T)l; see if its changed°dONLNdı‡`Îy(~beq.s°dONLNd˚‡ÑÎù)$@FixB°dONLNd‡ÎJ)l; A is done if not°dONLNdÍ`ıy(~sub.l°dONLNdÍÑıù)$#2,sp°dONLNd%Íı6)l; return param°dONLNd5Ù`ˇ~(~move.l°dONLNd<ÙÑˇfi)$AStrText(a6),-(sp)°dONLNdOÙˇ)l    ; textBuf°dONLNdZ˛`    ~(%~move.w°dONLNda˛Ñ    ¨)$d0,-(sp)°dONLNdk˛    ,)l ; textOffset°dONLNdy`ç(/~    _CharByte°dONLNdÑ`y*
  4379. tst.w°dONLNdäÑù)$(sp)+°dONLNdíh)l; on character boundary?°dONLNd¨`'y(C~ble.s°dONLNd≤Ñ'ù)$@FixB°dONLNd∫';)l; yes, continue°dONLNdÀ&`1y(M~sub.l°dONLNd—&Ñ1„)$#1,AInfo.StrPtr(A6)°dONLNdÂ&1@)l; adjust pointer°dONLNd˜0`;y(W~add.w°dONLNd˝0Ñ;„)$#1,AInfo.StrCnt(A6)°dONLNd0;6)l; adjust count°dONLNd :<EU(aZ@FixB°dONLNd'D`O~+$
  4380. move.w°dONLNd.DÑOœ)$BStrLen(a6), d0°dONLNd>DO")l
  4381. ; B length°dONLNdJN`Yy(u~sub.w°dONLNdPNÑY„)$BInfo.StrCnt(a6),d0°dONLNddNYT)l; see if its changed°dONLNdzX`cy(~beq.s°dONLNdÄXÑc±)$    Quit Init°dONLNdãXcJ)l; B is done if not°dONLNdüb`my(â~sub.l°dONLNd•bÑmù)$#2,sp°dONLNd≠bm6)l; return param°dONLNdΩl`w~(ì~move.l°dONLNdƒlÑw„)$BStrText(a6), -(sp)°dONLNdÿlw)l    ; textBuf°dONLNd„v`Å~(ù~move.w°dONLNdÍvÑű)$    d0, -(sp)°dONLNdıvÅ,)l ; textOffset°dONLNd    Ä`ãç(ß~    _CharByte°dONLNd    ä`ïy*
  4382. tst.w°dONLNd    äÑïù)$(sp)+°dONLNd    äïh)l; on character boundary?°dONLNd    6î`üy(ª~ble.w°dONLNd    <îÑü±)$    @QuitInit°dONLNd    Gîü;)l; yes, continue°dONLNd    Xû`©y(≈~sub.l°dONLNd    ^ûÑ©„)$#1,BInfo.StrPtr(A6)°dONLNd    rû©@)l; adjust pointer ◊X◊
  4383. (ÏZ(Modifying the Standard String Comparison(Ï3) of 8ˇV◊#ˇ ˇˇˇˇ#◊ 
  4384. IR,Times
  4385. .+6-Macintosh Technical Notes /4/˘,
  4386. Courier
  4387.     °dONLNd<(U+$add.w°dONLNd`(ø)$#1,BInfo.StrCnt(A6)°dONLNdÃ()l; adjust count°dONLNd)'2E(N6    @QuitInit°dONLNd41<<U+$
  4388. bra.s°dONLNd:1`<à)$ReturnEQ°dONLNdD1Ã<?)l; return to the caller.°dONLNd];<F_(bZEndWith
  4389. °dONLNde]l£(à6The Fetch Procedure
  4390. °dONLNdyxÑœ*'The Fetch Procedure is used to fetch a °dONLNd†xœÑ⁄)∑8character from a string, updating the pointer and length°dONLNdŸÑêû(¨6to reflect the remainder of °dONLNdıÑûê⁄)Ü=the string. For example, the following code changes the  text°dONLNd3êú°(∏6comparison for Yugoslavian:
  4391. °dONLNdO®¥Œ*I;------------------------------------------------------------------------°dONLNdô≥øN*     ; Routine°dONLNd£≥`øñ)H    FetchProc°dONLNd≠æ B(Ê6; Input°dONLNdµæ` &)H!A2          String Data Structure°dONLNd◊…’(Ò6;°dONLNd⁄…`’å)H2A3          String pointer (one past fetched char)°dONLNd
  4392. ‘‡$(¸6; °dONLNd‘`‡Í)HA6          Local Frame°dONLNd)flÎ(6;°dONLNd,fl`λ)H<D4.W        Character: top byte is fetched character, bottom°dONLNdi͈¸(6&;                              is zero°dONLNdêı* ;°dONLNdìı`n)H-D5.B        1 if string is empty, otherwise 0°dONLNd¡ H((6; Output°dONLNd ` ¬)H;D4.W        Character: top byte set to character, bottom to°dONLNd (36;°dONLNd     `fi)H            extension°dONLNd"(>6;°dONLNd"`"n)H-D5.B        1 if string is empty, otherwise 0°dONLNdP!-N(I6    ; Trashes°dONLNdZ!`-¥)HStandard regs:°dONLNdi!Ã-)l A0/A1/D0-D2°dONLNdu,8T(T6
  4393. ; Function°dONLNdÄ,`8∂)H9This routine returns the characters that are fetched from°dONLNd∫7C(_6;°dONLNdΩ7`C»)H<the string, if they are not just a sequence of single bytes.°dONLNd˙BNŒ(j6I;------------------------------------------------------------------------
  4394.     °dONLNdDYdE*    FetchProc°dONLNdOc<nU+$
  4395. tst.b°dONLNdUc`nj)$d5°dONLNdZcÃnX)l; more characters in string?°dONLNdxm<xU(îZbne.s°dONLNd~m`xà)$ReturnEq°dONLNdàmÃx!)l; no -> bail out.°dONLNdõÅ<åZ(®Zmove.w°dONLNd¢Å`åy)$d4,d0°dONLNd™ÅÃå!)l; load high byte.°dONLNdΩã<ñZ(≤Zmove.b°dONLNdƒã`ñÉ)$(a3),d0°dONLNdÕãÃñ)l; load low byte.°dONLNd·ü<™K(ΔZlea°dONLNdÂü`™ú)$ pairTable,a1°dONLNdÛüÙ0)l; load table address°dONLNd≥æT(⁄6 @compareChar°dONLNdΩ<»Z+$
  4396. move.w°dONLNdΩ`»à)$(a1)+,d1°dONLNd'Ωû)l ; pair = 0?°dONLNd4«<“U(ÓZbeq.s°dONLNd:«`“à)$ReturnEq°dONLNdD«Ã“:)l; yes -> end of table.°dONLNd\—<‹U(¯Zcmp.w°dONLNdb—`‹y)$d0,d1°dONLNdj—Ë?)l; legal character pair?°dONLNdÉ€<ÊU(Zbne.s°dONLNdâ€`Êú)$ @compareChar°dONLNdó€ÃÊI)l; no -> try the next one.°dONLNd≤Â<U( Zadd.w°dONLNd∏Â`y)$#1,a3°dONLNd¿ÂÃ0)l; increment pointer.°dONLNd÷Ô<˙U(Zsub.w°dONLNd‹Ô`˙°)$
  4397. #1,StrCnt(a2)°dONLNdÎÔÃ˙+)l; decrement length.°dONLNd˘<Z( Zaddx.w°dONLNd˘`y)$d5,d5°dONLNd˘ÃD)l; empty -> set the flag.°dONLNd)<Z(*Zmove.w°dONLNd0`y)$d0,d4°dONLNd8Ã:)l; copy character pair.°dONLNdP
  4398. <K(4Zrts°dONLNdW
  4399. Ãb)ê; return to caller with CCR=NE°dONLNdv!,E(H6    pairTable°dONLNdÅ+<6P+$
  4400. dc.b°dONLNdÜ+`6t)$'Lj'°dONLNdç+Ã6‡)l; Lj°dONLNdì5<@P(\Zdc.b°dONLNdò5`@t)$'LJ'°dONLNdü5Ã@‡)l; LJ°dONLNd•?<JP(fZdc.b°dONLNd™?`Jy)$'lJ' °dONLNd≤?ÃJ‡)l; lJ°dONLNd∏I<TP(pZdc.b°dONLNdΩI`Tt)$'lj'°dONLNdƒIÃT‡)l; lj°dONLNdÃ]<hP(ÑZdc.b°dONLNd—]`ht)$'Nj'°dONLNdÿ]Ãh‡)l; Nj°dONLNdfig<rP(éZdc.b°dONLNd„g`rt)$'NJ'°dONLNdÍgÃr‡)l; NJ°dONLNdq<|P(òZdc.b°dONLNdıq`|t)$'nJ'°dONLNd¸qÃ|‡)l; nJ°dONLNd{<ÜP(¢Zdc.b°dONLNd{`Üt)$'nj'°dONLNd{Ã܇)l; nj ◊4◊˘
  4401. (Ï64) of 8(ÏK(Modifying the Standard String Comparisonˇ⁄◊#ˇ ˇˇˇˇ#◊ 
  4402. IR,Times
  4403. .+Z-Developer Support Center(-Ï
  4404. March 1988 /X/,
  4405. Courier
  4406.     °dONLNd'`2t(N~dc.b°dONLNd'Ñ2¨)$'D', $be°dONLNd'2)l; Dz-hat°dONLNd1`<t(X~dc.b°dONLNd1Ñ<¨)$'D', $ae°dONLNd(1<)l; DZ-hat°dONLNd2;`Ft(b~dc.b°dONLNd7;ÑF¨)$'d', $ae°dONLNdA;F)l; dZ-hat°dONLNdKE`Pt(l~dc.b°dONLNdPEÑP¨)$'d', $be°dONLNdZEP)l; dz-hat°dONLNddY`dt(Ä~DC.B°dONLNdiYÑd¨)$$00, $00°dONLNdsYd')l ; table end°dONLNdo<zi(ñZ    FetchProc°dONLNdäy`Ñt+$
  4407. with°dONLNdêy®Ñ’)H    IUStrData°dONLNdõÉ`éy(™~tst.b°dONLNd¢É®é≤)Hd5°dONLNdßÉé_)l; empty string?°dONLNd∏ç`òy(¥~bne.s°dONLNdøç®ò–)HReturnEq°dONLNd…çòx)l; exit if length = 0°dONLNd‡°<¨@(»Z4; if we have a double-byte char, add the second byte°dONLNd´`∂o+$
  4408. lea°dONLNd´®∂Ó)HCurChar(a2),a0°dONLNd*´∂Z)l; pass pointer°dONLNd:µ`¿~(‹~move.w°dONLNdBµ®¿À)Hd4,(a0)°dONLNdKµ¿n)l; set value at ptr°dONLNd_ø` y(Ê~clr.w°dONLNdfø® ≤)Hd0°dONLNdkø U)l
  4409. ; pass length°dONLNdz”`fiy(˙~sub.l°dONLNdÅ”®fi¡)H#2,SP°dONLNdâ”fii)l; allocate return°dONLNdú›`Ë~(~move.l°dONLNd§›®Ë–)Ha0,-(sp)°dONLNdÆ›ËA)l    ; pointer°dONLNdπÁ`Ú~(~move.w°dONLNd¡Á®Ú–)Hd0,-(sp)°dONLNdÀÁÚ<)l; offset°dONLNd’Ò`¸ç(~    _CharByte°dONLNd‡˚`y*
  4410. tst.w°dONLNdÊ˚Ñù)$(sp)+°dONLNdÓ˚1)l
  4411. ; test return°dONLNd˝`y(,~bmi.s°dONLNdѪ)$ @DoubleByte°dONLNdã)l; skip if high byte (first two)°dONLNd1<$©(@ZI; we don’t have a double byte, but two special cases combine second bytes°dONLNd|#`.~+$
  4412. move.b°dONLNdÉ#Ñ.¨)$(a3),d0 °dONLNdé#._)ê; get next byte°dONLNdü-`8y(T~cmp.b°dONLNd•-Ñ8ß)$#$DE,d0°dONLNdØ-8A)ê    ; nigori?°dONLNd∫7`By(^~beq.s°dONLNd¿7ÑBª)$ @DoubleByte°dONLNdŒ7B<)ê; add in°dONLNdÿA`Ly(h~cmp.b°dONLNdfiAÑLß)$#$DF,d0°dONLNdËAL7)ê; maru?°dONLNdÒK`Vy(r~bne.s°dONLNd˜KÑV¨)$ReturnEq°dONLNdKVs)ê; exit: single byte°dONLNd_<js(ÜZ @DoubleByte°dONLNd#i`t~+$
  4413. move.b°dONLNd*iÑt¨)$(a3)+,d4°dONLNd5it_)ê; get next byte°dONLNdFs`~~(ö~subq.w°dONLNdMsÑ~≈)$
  4414. #1,StrCnt(A2)°dONLNd]s~s)ê; dec string length°dONLNdr}`à~(§~addx.w°dONLNdy}Ñàù)$d5,d5°dONLNdÇ}àõ)ê set x=1 if string len = 0°dONLNdüá`ío(Æ~rts°dONLNdßáí™)¥; return to caller with CCR=NE
  4415. °dONLNdΔ©<∏”(‘ZThe Project Procedure
  4416. °dONLNd‹ƒ<–\*;The Project Procedure is used to find the primary ordering °dONLNdƒ\–˛(Ïz"for a character. This routine will°dONLNd:–<‹Ö(¯Zmap characters °dONLNdI–Ö‹˛)IQthat differ only in the secondary ordering onto a single character, typically the°dONLNdõ‹<Ë(ZYunmodified, uppercase character. For example, the following changes the comparison order °dONLNdÙ‹˲(for°dONLNd¯Ë<ÙG(Z8some Norwegian characters, so that they occur after ‘Z.’
  4417.     °dONLNd1< ©*I;------------------------------------------------------------------------°dONLNd{
  4418. <i*
  4419.     ; Routine°dONLNdÖ
  4420. Ѫ)H ProjectProc°dONLNdë<_(;Z; Input°dONLNdôÑ))H!A2          String Data Structure°dONLNdª<)A(EZ;°dONLNdæÑ)∞)H<D4.W        Character (top byte is char, bottom is extension°dONLNd˚(<3A(OZ;°dONLNd˛(Ñ3∞)H<            (the extension is zero unless set by FetchProc))°dONLNd;2<=d(YZ; Output°dONLNdD2Ñ=)HD4.W        Projected Character°dONLNdd<<GA(cZ;°dONLNdg<ÑG=)H%CCR         NE to skip normal Project°dONLNdçF<Qi(mZ    ; Trashes°dONLNdóFÑQ )HStandard regs:°dONLNd¶FQ')l A0/A1/D0-D2°dONLNd≤P<[n(wZ
  4421. ; Function°dONLNdΩPÑ[´)H;This routine projects the secondary characters onto primary°dONLNd˘Z<e“(ÅZ;                  characters.°dONLNdd<oA*
  4422. ;°dONLNddÑo„)HExample: a,ä,Ä -> A°dONLNd/n<y©(ïZI;------------------------------------------------------------------------°dONLNdyÇ<çs* ProjectProc°dONLNdÜå`óo+$
  4423. lea°dONLNdäåÑó¿)$ ProjTable,A1°dONLNdóåÃó5)H; load table address.°dONLNd≠ñ<°i(ΩZ    @findChar°dONLNd∏†`´~+$
  4424. move.l°dONLNdø†Ñ´¨)$(a1)+,D0°dONLNd…†´')l ; get entry ◊X◊
  4425. (ÏZ(Modifying the Standard String Comparison(Ï5) of 8ˇä◊#ˇ ˇˇˇˇ#◊ 
  4426. IR,Times
  4427. .+6-Macintosh Technical Notes /4/˘,
  4428. Courier
  4429.     °dONLNd<(U+$cmp.w°dONLNd`(y)$d0,d4°dONLNdÃ(+)l; original ≥ entry?°dONLNd#'<2U(NZbhi.s°dONLNd)'`2ç)$    @findChar°dONLNd4'Ã2I)l; no, try the next entry.°dONLNdO1<<U(XZbne.s°dONLNdU1`<à)$ReturnEq°dONLNd_1Ã<])l; not equal, process normally°dONLNd}EPT(l6 @replaceChar°dONLNdãO<ZP+$
  4430. swap°dONLNdêO`Zj)$d0°dONLNdïOÃZ!)l; get replacement°dONLNd®Y<dZ(ÄZmove.w°dONLNdØY`dy)$d0,d4°dONLNd∑YÃdI)l; set new character word.°dONLNd—cnE(ä6    @doneChar°dONLNd‹m<xK+$
  4431. rts°dONLNd„mÃxX)ê; CCR is NE to skip project.°dONLNdÅåE(®6    ProjTable°dONLNd ãñ*
  4432. ;°dONLNdã<ñ;)$3Table contains entries of the form  r1, r2, o1, o2,°dONLNdBï†(º6;°dONLNdDï<†    )$)where r1,r2 are the replacement word, and°dONLNdoü™(Δ6;°dONLNdqü<™Ê)$"o1, o2 are the original character.°dONLNdî©¥(–6;°dONLNdñ©<¥r)$>The entries are sorted by o1,o2 for use in the above algorithm°dONLNd÷Ω<»P*DC.B°dONLNd€Ω`»¶)$'Z', 3, 'Å', 0°dONLNdÍΩû)l ; Å after Ø°dONLNd˜«<“P(ÓZDC.B°dONLNd¸«`“¶)$'Z', 3, 'å', 0°dONLNd «Ã“)l ; å after Ø°dONLNd—<‹P(¯ZDC.B°dONLNd—`‹¶)$'Z', 1, 'Æ', 0°dONLNd,—Ë)l ; Æ after Z°dONLNd9€<ÊP(ZDC.B°dONLNd>€`ʶ)$'Z', 2, 'Ø', 0°dONLNdM€ÃÊ)l ; Ø after Æ°dONLNdZÂ<P( ZDC.B°dONLNd_Â`¶)$'Z', 1, 'æ', 0°dONLNdnÂÃ)l ; æ after Z°dONLNd{Ô<˙P(ZDC.B°dONLNdÄÔ`˙¶)$'Z', 2, 'ø', 0°dONLNdèÔÃ˙)l ; ø after Æ°dONLNdú˘<P( ZDC.L°dONLNd°˘`ç)$    $FFFFFFFF°dONLNd¨˘Ã)l ; table end
  4433. °dONLNd∏ (76/The Project procedure can also be used to undo °dONLNdÁ ⁄)Ù)the effects of the normal projection. For°dONLNd'∫(C6Wexample, suppose that “œ” is not to be expanded into “oe”: in that case, a simple test °dONLNdh∫'⁄(Cÿcan be°dONLNdo(4®(P6made against 'œ',0, returning °dONLNdç'®3∂)êNE°dONLNdè(∂4†)4 if there is a match, so that the normal processing °dONLNd√(†4⁄)Í is not done.°dONLNd–4@¢(\6RTo expand one character into two, the routine should return the first replacement °dONLNd"4¢@⁄(\¿ character in°dONLNd/@L4(i6D4.W°dONLNd3A4M√), and modify two fields in the °dONLNdR@√L)è    IUStrData°dONLNd[AMÄ)? field. For example, given °dONLNdvAÄMï)~that °dONLNd{@ïL£)A1°dONLNd}A£M⁄)  points to a°dONLNdäMYq(u6Ftable entry of the form (primaryCharacter: Word; secondaryCharacters: °dONLNd–MqY⁄(uèWord), the following°dONLNdÂYeu(Å6code could be used:
  4434.     °dONLNd˙q<|A+$…°dONLNd˝{<ÜZ*
  4435. move.w°dONLNd{`Üà)$(a1)+,d4°dONLNd{ÃÜq)l!; return first, primary character°dONLNd1Ö<êZ(¨Zmove.w°dONLNd8Ö`êµ)$(a1)+,CurChar(A2)°dONLNdJÖÃê{)l#; original => first, modified char.°dONLNdoè<öZ(∂Zaddq.b°dONLNdvè`ö∞)$#1,JustAfter(A2)°dONLNdáèÃö])l; set to one (otherwise zero)°dONLNd¶ô<§Z(¿Zmove.b°dONLNd≠ô`§∞)$(a1),BufChar(A2)°dONLNdæôçl)l ; store second character (BYTE!),    Geneva°dONLNd‡£<ØD(ÃZ…
  4436. °dONLNd‚ª«I(‰6CurChar°dONLNdȺI»à)1 is where the °dONLNd˜ºà»)?original character returned by °dONLNdª«X)ë    FetchChar°dONLNdºX»⁄)? is stored. If characters are°dONLNd=…’(Ò6Odifferent even after being projected onto their respective primary characters, °dONLNdå…’©(Òù    then the °dONLNdﻩ‘⁄)*CurChar°dONLNdù÷‚e(˛6values for each °dONLNd≠÷e‚„)Mstring will be compared. °dONLNdΔ’„·")~    JustAfter°dONLNdœ÷"‚⁄)?& indicates that the expanded character°dONLNdˆ‚Ó(
  4437. 6/should sort after the corresponding unexpanded °dONLNd%‚Ó⁄)ˆ%form. This field must be set whenever°dONLNdKÓ˙I(6CurChar°dONLNdRÔI˚)1, is modified in order for the comparison to °dONLNd~Ô˚u)‘be fully ordered. °dONLNdêÓu˙¶)XBufChar°dONLNdóÔ¶˚⁄)1  stores the°dONLNd£¸‰($6-next byte to be retrieved from the string by °dONLNd–˚‰#)à   FetchChar°dONLNdŸ¸#')?.°dONLNd€ .(<6;To handle the case where characters are ignored unless the °dONLNd. ⁄(<L"two compared strings are otherwise°dONLNd9!-I(I6 equal, the °dONLNdD I,z)1IgnChar°dONLNdK!z-)1 flag can be set. This can be °dONLNdi!-⁄)Ü,used to handle characters such as the hyphen°dONLNdñ-9∞(U6 in English, or vowels in Arabic.
  4438.     °dONLNd∏E<PA+$…°dONLNdªO<ZU*
  4439. cmp.w°dONLNd¡O`Zí)$
  4440. #hyphen,d0°dONLNdÕOÃZ0)l; is it a ignorable?°dONLNd„Y<dK(ÄZseq°dONLNdÁY`dó)$ IgnChar(a2)°dONLNdÙYÃd0)l; set whether or not°dONLNd    
  4441. c<nA(äZ… ◊4◊˘
  4442. (Ï66) of 8(ÏK(Modifying the Standard String Comparisonˇ2◊#ˇ ˇˇˇˇ#◊ 
  4443. IR,Times
  4444. .+Z-Developer Support Center(-Ï
  4445. March 1988 /X/
  4446. °dONLNd)<8◊(TZThe Vernier Procedure
  4447. °dONLNdD<P•*JThe Vernier Procedure is used to make a final comparison among characters °dONLNd`D•P˛(l√that have the same°dONLNdsQ<](yZ+primary ordering. It is only needed if the ,
  4448. Courier°dONLNdûP\@)”CurChar°dONLNd•Q@]h)1 values °dONLNd≠Qh]˛)(are not ordered properly. For°dONLNdÀ]<ij(ÖZ    example, °dONLNd‘]ji˛).Raccording to the binary encoding, å < Ã. To change this ordering so that uppercase°dONLNd'i<ur(ëZCletters are before lowercase letters, Ã is mapped to $7F in normal °dONLNdjiru˛(ëêcomparison. Notice that only°dONLNdáu<Åb(ùZ@the characters in the secondary ordering are affected: Ã can be °dONLNd«ubŞ(ùÄmapped onto Z, but not onto Ä,°dONLNdÊÅ<ç›(©Z#since that would cause a collision.
  4449.     °dONLNd
  4450. ô<§©*I;------------------------------------------------------------------------°dONLNdT£<Æi*
  4451.     ; Routine°dONLNd^£Ñƪ)H VernierProc°dONLNdj≠<∏_(‘Z; Input°dONLNdr≠Ñ∏¿)H D4.B        °dONLNdÄ≠∏^)lHigh byte of character°dONLNdó∑<¬A(fiZ;°dONLNdö∑Ѭª)H D5.B       °dONLNd¶∑ì:)H Low byte of character°dONLNdΩ¡<Ãd(ËZ; Output°dONLNdΔ¡Ñê)H D4.B       °dONLNd“¡ÃÃ?)H High byte of character°dONLNdÍÀ<÷A(ÚZ;°dONLNdÌÀÑ÷ª)H D5.B       °dONLNd˘ÀÃ÷:)H Low byte of character°dONLNd’<‡A(¸Z;°dONLNd’чª)H CCR        °dONLNd’Çg)H NE if to skip standard Vernier°dONLNd?fl<Íi(Z    ; Trashes°dONLNdIflÑÍ )HStandard regs:°dONLNdXflÍ')l A0/A1/D0-D2°dONLNddÈ<Ùn(Z
  4452. ; Function°dONLNdoÈÑÙ∞)H<The Vernier routine compares characters within the secondary°dONLNd¨Û<˛ñ(Z;                 °dONLNdøÛ®˛â)l- ordering if two strings are otherwise equal.°dONLNdÌ˝<ñ($Z;                 °dONLNd˝®)l Example: (a,A,Ä,ä)°dONLNd<©(.ZI;------------------------------------------------------------------------°dONLNd^<&s* VernierProc°dONLNdl%`0y+$
  4453. not.b°dONLNds%®0≤)Hd4°dONLNdw%0w)H invert secondary ordering°dONLNdî/`:y(V~not.b°dONLNdõ/®:≤)Hd5°dONLNdü/:^)H; ditto for lower byte°dONLNd∑9`Dy(`~bra.s°dONLNdæ9®D–)HReturnEq°dONLNd«9DÜ)H; normal processing afterwards
  4454. °dONLNdÊ[<jî(ÜZInstalling an °dONLNdÙ\îk∏)Xitl2°dONLNd¯[∏jˆ)$     resource
  4455. °dONLNdw<É~(üZ To write an °dONLNdv~Çö)Bitl2°dONLNdwöÉP)$ resource, follow the guidelines in °dONLNd7wPɲ)∂M.PT.StandAloneCode for writing°dONLNdWÉ<èfl(´ZUstandalone code in MPW. The code should be written in assembly language, and it must °dONLNd¨Éflè˛(´˝follow°dONLNd≥è<õK(∑Z;the specifications given in this technical note or serious °dONLNdÓèKõ˛(∑i"system errors could occur whenever°dONLNdõ<ß«(√Zstring comparisons are made.°dONLNd.¥<¿*)The default comparison routine is in the °dONLNdW≥ø)≈itl2°dONLNd[¥¿÷)' resource of the System file. In order °dONLNdÇ¥÷¿˛)πto use a°dONLNdã¡<Õ (ÈZ0comparison routine other than the standard one, °dONLNdª¡ Õè)‰you should include an °dONLNd—¿èô)oitl2°dONLNd’¡´Õ˛) resource in your°dONLNdÁÕ<Ÿ(ıZ,application with the same name and resource °dONLNdÕŸ˛)’1ID as the one in the System file that you wish to°dONLNdEŸ<°(ZKchange. The Resource Manager will look for the resource in the application °dONLNdêŸ°Â˛(øresource file before°dONLNd•Â<Ò•(
  4456. Zit looks in the System °dONLNdº•Ò˛)iHresource file, so your string comparison routine will be used instead of°dONLNdÒ<˝Ö(Zthe default one.°dONLNd    <ê*GIt is generally a dangerous practice to change a system resource since °dONLNd]    ê˛(1Æother applications may°dONLNdt<"}(>Zdepend on it, °dONLNdÇ}"∂)A>but if you have good reasons to permanently change the system °dONLNd¿∂!“(>‘itl2°dONLNdƒ“"˛)     resource°dONLNdŒ"<.p(JZBso that all applications use a different comparison routine, then °dONLNd    "p.˛(Jéyou should write an installer°dONLNd    ./<;û(WZscript to change the °dONLNd    C.û:∫)bitl2°dONLNd    G/∫;\)! resource in the System resource °dONLNd    h/\;˛)¢$file. Writing an installer script is°dONLNd    ç;<G#(cZ/documented in M.TP.Installer. You are required °dONLNd    º;#G˛)Á0to write an installer script if you are planning°dONLNd    ÌG<Si(oZ<to ship your application on a licensed system software disk °dONLNd
  4457. )GiS˛(oáand your application makes a°dONLNd
  4458. FS<_/({Z0permanent change to any resources in the System °dONLNd
  4459. vS/_˛)Û)file. We strongly discourage changing the°dONLNd
  4460. †`<ld(àZSystem °dONLNd
  4461. ß_dkÄ)(itl2°dONLNd
  4462. ´`ÄlC)& as that would change the behavior of °dONLNd
  4463. —`Cl˛)√%string comparison and sorting for all°dONLNd
  4464. ˜l<xÏ(îZ]applications. If that is your intent, then you should write an installer script. However, if °dONLNd TlÏx˛(î
  4465. you°dONLNd Xy<Ö{(°Z
  4466. are changing °dONLNd ey{Öç)?the °dONLNd ixçÑ©)itl2°dONLNd my©Ö˛)G resource in the System file for academic or internal use, then you can°dONLNd µÜ<í-(ÆZ3use a resource editor such as ResEdit to copy your °dONLNd ËÖ-ëI)Òitl2°dONLNd ÏÜIí÷) resource into the System file. ◊X◊
  4467. (ÏZ(Modifying the Standard String Comparison(Ï7) of 8ˇ¯◊#ˇ ˇˇˇˇ#◊ 
  4468. IR,Times
  4469. .+6-Macintosh Technical Notes /4/˘
  4470. °dONLNd)5Ç*$Further Reference: T4T˘°dONLNd6*B.+
  4471. •°dONLNd6<B¥)The International Utilities°dONLNd1B*N.(jH•°dONLNd3B<NÇ)M.TP.Installer°dONLNdBN*Z.(vH•°dONLNdDN<Z¨)M.PT.StandAloneCode ◊4◊˘
  4472. (Ï68) of 8(ÏK(Modifying the Standard String Comparisonˇ|◊#ˇ ˇˇˇˇ#◊†Ç 
  4473. /ZÅ#
  4474.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4475. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4476. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4477. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4478. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4479.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4480. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  4481. IR.°dONLNdz<çÄ(ßZ%Styled TextEdit Changes in System 6.0
  4482. °dONLNd&å<õZ*Text°dONLNd,åcõ˛(∑ÅM.TE.TextEditChanges
  4483. °dONLNdAß<≥t(œZ Revised by:°dONLNdMßÑ≥≈)H
  4484. Chris Derossi°dONLNd[ߥ≥˛(œ“
  4485. December 1988°dONLNdi≥<øq(€Z Written by:°dONLNdu≥Ñø≈)H
  4486. Chris Derossi°dONLNdÉ≥¡ø˛(€fl August 1988°dONLNdèÀ<◊h(ÛZ<Some changes were made to TextEdit in System 6.0 to provide °dONLNdÀÀh◊˛(ÛÜmore functionality and to make°dONLNdÍ◊<„P(ˇZlife °dONLNdÔ◊P„˛)Peasier for the programmer using TextEdit.  This Note documents those changes and°dONLNd@„<ÔÇ( Z
  4487. enhancements.°dONLNdN<¸ë*
  4488. Changes since °dONLNd\븄)U
  4489. August  1988:°dONLNdi„¸T)R  Corrected an error in ,
  4490. Courier°dONLNdÅÔT˚Ø)q
  4491. TEDispatchRec°dONLNdéظ˛)[ in the figure on°dONLNd†¸<_($Zpage 8. 3X3
  4492. °dONLNd®-<<±*4TextEdit Changes
  4493. °dONLNdπH<T›*"In order to improve the usability °dONLNd€H›T˛)°8of styled TextEdit, some routines have been changed, and°dONLNdT<`ˆ(|Z[some new routines have been added.  These changes exist in System Software 6.0 and later.  °dONLNdoTˆ`˛(|If°dONLNdr`<l(àZ+you intend to rely on any of these changes °dONLNdù`l˛)‹.or new routines, it is important that you call°dONLNdÃl<xê(ïZ _SysEnvirons°dONLNdÿmêy‡)TG first to make sure you are running under System Software 6.0 or later.°dONLNd Ö<ëê(ÆZ _SysEnvirons°dONLNd,Üêí")T is documented in °dONLNd>Ü"íÉ)íInside Macintosh°dONLNdNÜÉí˛)a, Volume V and°dONLNd]í<û√(∫ZM.OV.GestaltSysenvirons. °dONLNdví√û˛)á; To check for the styled TextEdit changes, you might do the°dONLNd≤û<™m(ΔZ
  4494. following:
  4495.     °dONLNdæ∂`¡o+$VAR°dONLNdƒ¿ÑÀ±+$
  4496.     theWorld:°dONLNdŒ¿ÃÀ˛)H
  4497. SysEnvRec;°dONLNd€ Ñ’ù(Ò¢anErr°dONLNd· ®’≠)$:°dONLNd„ Ã’Í)$OSErr;°dONLNdÎfi`Èy(~BEGIN°dONLNdÛËÑÛ.+$
  4498. "anErr := SysEnvirons(1, theWorld);°dONLNdÚÑ˝ø*
  4499. ?IF (anErr = noErr) AND (theWorld.systemVersion >= $0600) THEN …°dONLNd\¸®+$
  4500. {System 6.0 or later}°dONLNds`t(-~END;
  4501. °dONLNdx(<7˛(SZChanges to Existing Routines
  4502. °dONLNdïC<Of*_TEKey°dONLNdõDfPÉ)* and _°dONLNd°CÉOª)TEDelete°dONLNd©DªPæ)8 °dONLNd™DæP˛)Ahave been changed so that backspacing to the beginning of a style°dONLNdÏQ<]+(yZ5no longer deletes that style.  Instead, the style is °dONLNd!Q+]l)Ô
  4503. saved in the °dONLNd.Pl\´)A    nullScrap°dONLNd7Q´]˛)? to be applied to°dONLNdI]<i–(ÖZsubsequently typed characters. °dONLNdh]–i˛)î= As soon as the user has backspaced past the beginning of the°dONLNd¶i<u{(ëZGstyle, or clicked in some other area of the text, the style is removed.°dONLNdÓÅ<çê* GetStylScrap°dONLNd˙ÇêéÛ)TD now returns a handle to a valid style scrap record when called for °dONLNd>ÇÛé˛(™an°dONLNdAè<õã(∑Zinsertion point (°dONLNdRéãö√)OselStart°dONLNdZè√õ‘)8 = °dONLNd]é‘ö˛)selEnd°dONLNdcè˛õ)*).  °dONLNdgéö%)NIL°dONLNdjè%õ*) °dONLNdkè*õú)is still returned when °dONLNdÇéúö)r GetStylScrap°dONLNdéèõ˛)T is°dONLNdíú<®´(ƒZcalled with an old style °dONLNd´õ´ß„)oTEHandle°dONLNd≥ú„®Á)8. ◊X◊
  4504. (ÏZ%Styled TextEdit Changes in System 6.0(Ï1) of 7ˇ°¿Ù%%DSIDICT:_cv
  4505. currentdict /bu known {bu}if
  4506. userdict /_cv known not{userdict /_cv 30 dict put}if
  4507. _cv begin
  4508. /bdf{bind def}bind def
  4509. currentscreen/cs exch def/ca exch def/cf exch def
  4510. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4511. /ss{//cf //ca //cs setscreen}bdf
  4512. /stg{ss setgray}bdf
  4513. /strgb{ss setrgbcolor}bdf
  4514. /stcmyk{ss cvcmyk}bdf
  4515. /min1{dup 0 eq{pop 1}if}bdf
  4516. end
  4517. currentdict /bn known {bn}if
  4518. †ø"◊#ˇ ˇˇˇˇ#◊ 
  4519. IR,Times
  4520. .+6-Macintosh Technical Notes /4/˘,
  4521. Courier
  4522. °dONLNd)5^*%
  4523. TESetStyle°dONLNd
  4524. *^6)F! now accepts an additional mode, °dONLNd+)5<)¶doToggle°dONLNd3*<6@)8 °dONLNd4*@6D)(°dONLNd5)D5b)= 32°dONLNd9*b6ï)    ).  When °dONLNdB)ï5Õ)3doToggle°dONLNdJ*Õ6⁄)8 is°dONLNdN7C}(_6specified along with °dONLNdc6}Bß)edoFace°dONLNdi7ßCØ)*, °dONLNdk6ØBı)
  4525. TESetStyle°dONLNdu7ıCæ)F, operates as follows:  If a style specified °dONLNd°7æC⁄)…in the°dONLNd®DP7(l6given °dONLNdÆC7Ov)    TextStyle°dONLNd∑DvPp)?4 parameter exists across the entire selected range, °dONLNdÎDpP⁄)˙that style is removed°dONLNdP\Y(x6(turned off).  °dONLNdPY\⁄)ATOtherwise, all of the selected text is set to include that style.  When a particular°dONLNde\h (Ñ6cstyle is set for an entire selection range, that style is said to be continuous over the selection.°dONLNd…tÄM*DFor example, given that the following text is the current selection:†09†Ç
  4526. ´x∂ò*.dì¨.jì®´x∂⁄ˇÄŸÿ€€*|ÿÃ`˛ÄIJ ¯¿0IJ);Ä` ¿`˛Ä ˝ ¿¿20IJ*&¿`ÃxÃ6q √«Ä¿ÒÒ‡0yôè˛+)`Ãà Ã`3#8…ò úfdc¡ôò¿81ôôÄ+)xÃÃåÃ`30¡òòfc„Òôò¿1ôôÄ+)¿`ø Ã`?30¡ò òffc¡ôò¿1ôüÄ*&¿`ÿ Ã`030¡ò òffc¡ôò¿1ôò˛+)?Ä`à Ã`130…ò òffc¡ôò¿&1ôòÄ*&`Ãx«Ã00qò fc·Ä¿Òò`˘è˛›˝    fi˝›˝ÿÿ⁄ˇ⁄™†⁄ˇÄŸÄŸÄŸø˜Èˇ¿3Δ00˛ˇÄ@Ë300˚ø@Èˇ¿3><œ1·˛ˇÄ@Ë33Δ330˚ø@Èˇ¿33Δ330˛ˇÄ@Ë33Δ3Û0˚ø@Èˇ¿33Δ30˛ˇÄ@Ë33Δ30˚ø@Èˇ¿3 √1·˛ˇÄ@€ø˜Èˇ¿˙˛ˇÄŸÄŸÄŸ⁄ˇÄŸÄŸÄŸÄŸ
  4527. Ä¿˜    Äˆ    Äˆ    Äˆ    Äˆ    Äˆ    Äˆ    Äˆ    Äˆ    Äˆ    Äˆ    Äˆ    ÄˆįÒˇˆįÒˇˆ* Ä`c˛ˇèˇˇ¸œ˝ˇœ˛ˇ
  4528. Ò¿"$Ä`˝c˛ˇ?ˇˇ¸œ˝ˇœ˛ˇÒ¸"¸+)ÄcåÇ{·¿Ç< p|<œ¸||Ç<x1à YÜ0:√¬0+)ÄfÃÃc≥`àô?91˘úœ˘99àô8ëífIH#$Ç"@+Älg¯c60ôìü3ìˇœÁ˛'?ôìôë!!DPÑÑ"(@bÄ+ÄÏg¯‡c7ôê3츜Á˛'?ôêë!!D_ÑÑ"/¡¢Ä+ÄÏc00c6ôìˇ3ì˘úœŒ˛Nôì˘ë!!DPÑ"("Ä+)Äf√0c3`ôô?93˘œ‰d‰‰ôô9ëíDIH"$Çb@+)ÄcÉ0‡;1¿Dôú<s¸Lœ‡„„‡ˇôúyêà DF0#í0į˘ˇ¸˙ˇÙį˘ˇì˙ˇÙį˘ˇ«˙ˇÙÄŸÄŸĢ˘IJ$˛ÙĢ˘IJ$˛ÙĢ˘IJ$˛ÙĢ˘@˛B˛ÙĢ˘@˛B˛ÙįÄ˙ ˛Å˛Ùˆ@˙    ÄÙˆ0˙    ` `0Ùˆˇˇ˛˛ˇ    Ä¸¯‡?¿ÙÛ¸ ˛0`ÛÚà¸˛ÄÛÚP˚†˛ÚÚp˚‡˛ÚÚ ˚@˛ÚÚ ˚@˛Ú◊◊◊◊Û ¯Ä@ÙÛ ÄAĆÄ@ÙÛ8dpÄB˛Ä·ë¿ÙÛ$îê·ë¬ÇöíR@ÙÛ$îêíRA"í©íR@ÙÛ$îêíRB¢é®íR@ÙÛ$îêíRDBí®íR@ÙÛ8dpíRD¢í©·ë¿Ù Ó·ë√M¶†É
  4529. IR°dONLNd˛
  4530. \*äthen the style °dONLNd˝\    x)Dbold°dONLNd!˛x
  4531. K), is continuous over the selection range and °dONLNdM˛K
  4532. ^)”the °dONLNdQ˝^    à)italic°dONLNdW˛à
  4533. ⁄)* style is not.  If°dONLNdj
  4534. ^(36
  4535. TESetStyle°dONLNdt ^Ë)F were called with a mode °dONLNdç ˢ)äof °dONLNdê
  4536. ˘#)doFace°dONLNdñ #8)* + °dONLNdô
  4537. 8p)doToggle°dONLNd° põ)8 and a °dONLNd®
  4538. õ⁄)+    TextStyle°dONLNd≤#B(@6tsFace°dONLNd∏B$j)*
  4539.  field of °dONLNd¬j#î)([bold]°dONLNd»î$J)*(, then the resulting selection would be:†09†Ç
  4540. Ox∂∂ò*¿f'Æ¿j'®Ox∂∂⁄ˇ¿ÿ ÿ €€(Û01Ä8˛>˝
  4541. ‡p¿˝(ÓÄ0Äd˛0˝
  4542. »¿˝*&ˇÉ1‡3¿`xxŸ«¿0<mˇ««Ä¡Êf<˛*&¸É3031ÄpÃå„&`0fqôëåfc‡Δff˛*&¸„3031Ä8Ã|√`<faôèåΔfcpΔff˛*&ˇÉ331ĸÃ√`0faôôåfc8Δf~˛*&ˇÉ331Ä ¿Ã√`0faôôåfcΔf`˛*&˛É331ÄLƒÃ√&`0faôôåfcòΔfb˛*&lÉ1‡0¿8x|¡Δ`0<aôèÜΔaÄpcÊ<˛›`˝    fi`˝    fi¿˝ÿÿ⁄ˇ¿
  4543. ⁄™Ä⁄ˇ¿
  4544. ÿÿ
  4545. ÿ˝ˇflÈˇÃc¿¿˛ˇ¿
  4546. @ËÃ`¿¿˚˝_ÈˇÃ¯Û<«á¿˛ˇ¿
  4547. @ËÃÃcÃÿ˚˝_ÈˇÃÃcÃÿ˛ˇ¿
  4548. @ËÃÃcœÃ¿˚˝_ÈˇÃÃcà ¿˛ˇ¿
  4549. @ËÃÃcÃL¿˚˝_ÈˇxÃ3 «á¿˛ˇ¿
  4550. @€˝ˇflÈˇ˘˛ˇ¿
  4551. ÿÿ
  4552. ÿ⁄ˇ¿ÿ
  4553. ÿÿ
  4554. ÿ‰cˆ
  4555. ‰ˆ‰ˆ
  4556. ‰ˆ‰ˆ
  4557. ‰ˆ‰ˆ
  4558. ‰ˆ‰ˆ
  4559. ‰ˆ‰ˆ
  4560. ‰ˆ‰ˆ
  4561. ¯Ûˇ¿˝ˆ¯Ûˇ¿˝ˆ*
  4562. aÄ`åÔˇˇœˇˇ€˛ˇ˝˛ˇ»˝ c  àÄ)aIJ垎øˇˇ€˛ˇ˝˛ˇ»¸ ˛ Ä+)
  4563. qé30gÅÔá*güåÈ„€˘sÁÀ¶yÈŒ`bÃ09Å÷†céÄ+)yõ30l¡éÕÜÈõoªg›€ˆm€≥ô∂Ê»ê$ì2H"A$`í¿+)
  4564. m±ü‡låÿΔÎ∫˜∑Ø˘€fiΩz˜ªØn…A
  4565. "Ñ$!B!
  4566. Ä+)g±ü‡gÅåflΔÎ∫∑ØÂ€fiΩz˜ª†n…A
  4567. "¸$!~
  4568. !
  4569. Ä+)
  4570. c±å¿`¡åÿÎ∫ˇ∑Ø›€ΩzıÔªØÓ…A
  4571. "Ä$!@!
  4572. Ä+)aõ ¿l¡åÕÜΪoªoŸ€Ÿ∑nœª∂Ó»ê$í"H"A$`íÄ+)
  4573. aé ¿gÄÏ«+ªüºÔÊ€Àü>_ªπÓΔ`b"0Ä— ë†bį˙ˇ˚˚ˇ¿Ò
  4574. ¯˙ˇo˚ˇ¿Ò¯˙ˇü˚ˇ¿Ò
  4575. ¯Ûˇ¿Òÿ
  4576. ÿ¯ ˚ÄÄÒ
  4577. ¯ ˚ÄÄÒ¯ ˚ÄÄÒ
  4578. ¯˚@@Ò¯˚@@Ò˜˚   Ò˜˚@Ò˜˚` ` ÄÒˆ
  4579. ˇˇ¸ˇˇÄć>Ù ˝00`Ù˝@ÄÛ†˝ÄÔÛ‡˝ÄÔÛ@˝˛ÔÛ@˝˛Ô◊◊◊◊Ù˛@P@ÄÙ¸¸@@@Ôı …ïÄfSL¨ı *V@ITÄ    R≤ı )‘@GT    N¢ı *T@IT    R¢ı *T@ITÄ    R¢ı …¥@&”M¢
  4580. ı¯Ó
  4581. ı¯Ó†É
  4582. IR°dONLNdÒ§∞Ç(Ã6On the other hand, if °dONLNd£ÇØ»)j
  4583. TESetStyle°dONLNd§»∞h)F  had been called with a mode of °dONLNd1£hØí)†doFace°dONLNd7§í∞ñ)* °dONLNd8§ñ∞¢)+ °dONLNd:£¢Ø⁄) doToggle°dONLNdC±Ω4(Ÿ6and a °dONLNdI∞4ºs)    TextStyle°dONLNdR±sΩv)? °dONLNdS∞vº†)tsFace°dONLNdY±†Ω»)*
  4584.  field of °dONLNdc∞»º)([italic]°dONLNdk±ΩÃ)8+, then the selected text would have become:†09†Ç
  4585. ËxQ∂ò*bfÀÆbjÀ®ËxQ∂⁄ˇ¿ÿ ÿ €€(Û01Ä8˛>˝
  4586. ‡p¿˝(ÓÄ0Äd˛0˝
  4587. »¿˝*&ˇÉ1‡3¿`xxŸ«¿0<mˇ««Ä¡Êf<˛*&¸É3031ÄpÃå„&`0fqôëåfc‡Δff˛*&¸„3031Ä8Ã|√`<faôèåΔfcpΔff˛*&ˇÉ331ĸÃ√`0faôôåfc8Δf~˛*&ˇÉ331Ä ¿Ã√`0faôôåfcΔf`˛*&˛É331ÄLƒÃ√&`0faôôåfcòΔfb˛*&lÉ1‡0¿8x|¡Δ`0<aôèÜΔaÄpcÊ<˛›`˝    fi`˝    fi¿˝ÿÿ⁄ˇ¿
  4588. ⁄™Ä⁄ˇ¿
  4589. ÿÿ
  4590. ÿ˝ˇflÈˇÃc¿¿˛ˇ¿
  4591. @ËÃ`¿¿˚˝_ÈˇÃ¯Û<«á¿˛ˇ¿
  4592. @ËÃÃcÃÿ˚˝_ÈˇÃÃcÃÿ˛ˇ¿
  4593. @ËÃÃcœÃ¿˚˝_ÈˇÃÃcà ¿˛ˇ¿
  4594. @ËÃÃcÃL¿˚˝_ÈˇxÃ3 «á¿˛ˇ¿
  4595. @€˝ˇflÈˇ˘˛ˇ¿
  4596. ÿÿ
  4597. ÿ⁄ˇ¿ÿ
  4598. ÿÿ
  4599. ÿ‰cˆ
  4600. ‰ˆ‰ˆ
  4601. ‰ˆ‰ˆ
  4602. ‰ˆ‰ˆ
  4603. ‰ˆ‰ˆ
  4604. ‰ˆ‰ˆ
  4605. ‰ˆ¯ˇˆ
  4606. ¯ˇˆ¯ˇˆ+
  4607. aÄ`åŒˇˇ«ˇˇ˛g˛ˇ˛˛ˇc˛ &aIJåœ˛ˇüˇˇ˛g˛ˇ˛˛ˇ¸ ¸+)
  4608. qé30gÅÔáÑÇ< p|<œ‡„„‡¯#«É`bÃ09Å÷Ä+)yõ30l¡éÕáúàô?91˘úœ»……»¯âìâê$ì2H"A$@*
  4609. m±ü‡låÿ«93'>g'˛9ü˝9Û2s3    A
  4610. "Ñ$!B*g±ü‡gÅåfl«93 >g'¯9ü˝9Û23    A
  4611. "¸$!~
  4612. +
  4613. c±å¿`¡åÿrfO¸ŒOÊs>˛rsÊd˛g    A
  4614. "Ä$!@+)aõ ¿l¡åÕÜrfd¸‰œ‰s?#''#ÊfNgê$í"H"A$@+)
  4615. aé ¿gÄÏ«$Ģ„ü‚fÃŒ<œ`b"0Ä— ëᝎÁ˙ˇÛ
  4616. ¯˘ˇ¸ü˙ˇÛ¯˘ˇ˛?˙ˇÛ
  4617. ¯ˇÛÿ
  4618. ÿÿ
  4619. ¯@Ù ¯@Ù
  4620. ¯@Ù ¯ÄÙ
  4621. ˜ÄÙ
  4622. ˜ÒÛ
  4623. ˜ÒÛ
  4624. ˆ¿Ú Ûˆ?˚ˇ¯˙ˇÛÔ ÎÔ ÎÔ@ÎÔ¿ÎÓÄÎÓÄÎ◊◊◊◊◊◊◊ ÒÄAĆÌ
  4625. ÒÄB˛ÄÌ Ò·ë¬ÇÃ¶Ì ÒíRA"í©Ì ÒíRB¢é®Ì ÒíRDBí®Ì ÒíRD¢í©Ì Ò·ë√M¶Ì†É
  4626. IR
  4627. °dONLNdóJY≤(u6New TextEdit Routines
  4628.  °dONLNdÆfró*Some new routines  °dONLNd¿fór_)have been added to TextEdit, °dONLNd›e_q÷)»TEContinuousStyle°dONLNdÓf÷r⁄)w,°dONLNdr~fi(õ6SetStylScrap, TECustomHook, °dONLNd sfiÔ)Δand°dONLNdrÔ~D)  TENumStyles°dONLNdsDö)U.  These routines °dONLNd-sö⁄)V
  4629. are described°dONLNd;ãa(ß6in detail below. ◊4◊˘
  4630. *E2) of 7(ÏY%Styled TextEdit Changes in System 6.0ˇ◊#ˇ ˇˇˇˇ#◊ 
  4631. IR,Times
  4632. .+Z-Developer Support Center(-fi
  4633. December 1988 /X/
  4634. °dONLNd)÷5c(QÙAssembly language note:°dONLNd6ÑB (^¢The new TextEdit routines °dONLNd26 Bi)àare called via the ,
  4635. Courier°dONLNdE5iA∂)] _TEDispatch°dONLNdQBÑN´(j¢@trap.  Following are the decimal selectors for the new routines: m†m’°dONLNdì[®g+$TEContinuousStyle°dONLNd•[wgÖ)œ10°dONLNd©g®s¸(êΔ SetStylScrap°dONLNd∂gwsÖ)œ11°dONLNd∫s®¸(úΔ TECustomHook°dONLNd«swÖ)œ12°dONLNdÀ®ãı(®Δ TENumStyles°dONLNd◊wãÖ)œ13 ™†™’
  4636. °dONLNd⁄§<≥ª(œZTEContinuousStyle
  4637. °dONLNdÌø<À‡*FFUNCTION TEContinuousStyle(VAR mode : Integer; VAR aStyle : TextStyle;°dONLNd9 ÷û+¥    hTE : TEHandle) : Boolean;
  4638. °dONLNdW·<Ì≥(
  4639. ZTEContinuousStyle°dONLNdh‚≥Ó‘)w gives °dONLNdo‚‘Ó˛)!>you information about the attributes of the current selection.°dONLNdØÔ<˚S(ZThe °dONLNd≥ÓS˙o)mode°dONLNd∑Ôo˚t) °dONLNd∏Ôt˚b)-parameter, which takes the same values as in °dONLNdÂÓb˙®)Ó
  4640. TESetStyle°dONLNdÔÔ®˚˛)F, specifies which°dONLNd¸<ˆ($Z$attributes should be checked.  When °dONLNd%˚ˆm)∫TEContinuousStyle°dONLNd6¸mØ)w returns, the °dONLNdD˚ØÀ)Bmode°dONLNdH¸À–) °dONLNdI¸–˛)    parameter°dONLNdS<r(0Z=indicates which of the checked attributes is continuous over °dONLNdêr˛(0êthe selection range and the°dONLNd¨< f(=ZaStyle°dONLNd≤f![)*8 parameter is set  to reflect the continuous attributes.°dONLNdÎ-<9≥(VZTEContinuousStyle°dONLNd¸.≥:⁄)w     returns °dONLNd-⁄9ˆ)'TRUE°dONLNd    .ˆ:]) if all of the attributes °dONLNd#.]:˛)g to be checked are continuous and°dONLNdD:<F_(cZFALSE°dONLNdI;_GÌ)#! if not.  In other words, if the °dONLNdj:ÌF    )émode°dONLNdn;    G“), parameter is the same before and after the °dONLNdö;“G˛)…
  4641. call, then°dONLNd•G<S≥(pZTEContinuousStyle°dONLNd∂H≥T⁄)w     returns °dONLNdøG⁄Sˆ)'TRUE°dONLNd√HˆT˙).°dONLNd≈a<m~(âZ
  4642. For example, °dONLNd“`~lı)BTEContinuousStyle°dONLNd„aım¡)w, is useful for marking the style menu items °dONLNda¡m˛)Ã based on the°dONLNdm<yç(ïZcurrent selection.
  4643.     °dONLNd0Ö`ê´+$mode := doFace;°dONLNdAè`ö_*
  4644. 3IF TEContinuousStyle(mode, aStyle, myTE) THEN BEGIN°dONLNdvô`§x*
  4645. 8{ There is at least one face that is continuous over the°dONLNd∞£`ÆÇ*
  4646. :  selection. Note that it might be plain which is actually°dONLNdÏ≠`∏ˆ*
  4647.   the absence of all styles. }°dONLNd
  4648. ∑Ѭà+$
  4649. 4CheckItem(styleMenu, plainItem, aStyle.tsFace = []);°dONLNdD¡ÑÃí*
  4650. 6CheckItem(styleMenu, boldItem, bold IN aStyle.tsFace);°dONLNd}ÀÑ÷¶*
  4651. :CheckItem(styleMenu, italicItem, italic IN aStyle.tsFace);°dONLNd∫’чß*
  4652. ...etc.°dONLNd√fl`Ͷ(~END ELSE BEGIN°dONLNd”È`Ù_*
  4653. 3{ No text face is common to the entire selection. }°dONLNd    ÛÑ˛G+$
  4654. 'CheckItem(styleMenu, plainItem, FALSE);°dONLNd3˝ÑB*
  4655. &CheckItem(styleMenu, boldItem, FALSE);°dONLNd\ÑL*
  4656. (CheckItem(styleMenu, italicItem, FALSE);°dONLNdáÑß*
  4657. ...etc.°dONLNdê`&t(B~END;
  4658. °dONLNdï1<=Ë(YZ"This function can also be used to °dONLNd∑1Ë=˛)¨9determine the actual values for those attributes that are°dONLNdÒ><J>(fZ8continuous for the selection.  Note that a field in the °dONLNd)=>I}(f\    TextStyle°dONLNd2>}J»)? record is only °dONLNdB>»J˛)K valid if the°dONLNdOK<Wµ(sZcorresponding bit is set °dONLNdhKµWÿ)yin the °dONLNdoJÿVÙ)#mode°dONLNdsKÙW˛)5 variable; otherwise the field contains garbage.  For°dONLNd©W<c¢(ZOexample, to determine the font, face, size, and color of the current selection:
  4659.     °dONLNd˙o`z7+$+mode := doFont + doFace + doSize + doColor;°dONLNd'y`Ñd*
  4660. 4continuous := TEContinuousStyle(mode, aStyle, myTE);°dONLNd]É`é*
  4661. !IF BitAnd(mode, doFont) <> 0 THEN°dONLNdÅçÑòG+$
  4662. '{ Font for selection = aStyle.tsFont. }°dONLNd™ó`¢t(æ~ELSE°dONLNd±°Ñ¨=+$
  4663. %{ More than one font in selection. }; ◊X◊
  4664. (ÏZ%Styled TextEdit Changes in System 6.0(Ï3) of 7ˇú◊#ˇ ˇˇˇˇ#◊ 
  4665. IR,Times
  4666. .+6-Macintosh Technical Notes /4/˘,
  4667. Courier
  4668.     °dONLNd'<2·+$!!IF BitAnd(mode, doFace) <> 0 THEN°dONLNd$1`<á+$
  4669. ;{ aStyle.tsFace contains the text faces (or plain) that are°dONLNdb;`FÏ*
  4670.   common to the selection. }°dONLNdÄE<PP(lZELSE°dONLNdáO`Zd+$
  4671. 4{ No text face is common to the entire selection. };°dONLNdΩc<n·(äZ!IF BitAnd(mode, doSize) <> 0 THEN°dONLNd·m`x#+$
  4672. '{ Size for selection = aStyle.tsSize. }°dONLNd
  4673. w<ÇP(ûZELSE°dONLNdÅ`å+$
  4674. %{ More than one size in selection. };°dONLNd8ï<†Ê(ºZ"IF BitAnd(mode, doColor) <> 0 THEN°dONLNd]ü`™-+$
  4675. ){ Color for selection = aStyle.tsColor. }°dONLNdà©<¥P(–ZELSE°dONLNdè≥`æ+$
  4676. &{ More than one color in selection. };
  4677. °dONLNd∂ ÷.(Ú6The °dONLNd∫….’â)
  4678. aStyle.tsFace°dONLNd« â÷)[ field is a bit tricky.  When °dONLNdÂ…’â)âTEContinuousStyle°dONLNdˆ â÷æ)w  returns a °dONLNd…æ’⁄)5mode°dONLNd◊„X(ˇ6that contains °dONLNd÷X‚Ç)@doFace°dONLNd◊Ç„Æ)*    , and an °dONLNd#÷Æ‚    ),
  4679. aStyle.tsFace°dONLNd0◊    „
  4680. )[ °dONLNd1◊
  4681. „i)field that contains °dONLNdE÷i‚À)\[bold, italic]°dONLNdS◊À„⁄)b, it°dONLNdX„Ô≥( 6Zmeans that the selected text is all bold and all italic, but may contain other text faces °dONLNd≤„≥Ô⁄( —as well.°dONLNdºÔ˚‚(6-None of the other faces will apply to all of °dONLNdÈÔ‚˚⁄) 3the selected text, or they would have been included°dONLNd¸5($6in the °dONLNd$˚5_)tsFace°dONLNd*¸_ï)*I field.  But if the tsFace field is the empty set ([] = plain), then all °dONLNds¸ï⁄($≥of the selected°dONLNdÉR(06text is plain.°dONLNdí!-Ó*/If the current selection range is an insertion °dONLNd¡!Ó-)÷point, °dONLNd» ,Ü)!TEContinuousStyle°dONLNdŸ!Ü-⁄)w returns the style°dONLNdÏ.:w(V6information for the °dONLNd.w:)_next character to be typed.  °dONLNd-9|)éTEContinuousStyle°dONLNd..|:⁄)w will always return°dONLNdB:F4(c6TRUE°dONLNdF;4G‘)% in this case, and each field of the °dONLNdk:‘F)†    TextStyle°dONLNdt;Gt)? record will be set if °dONLNdã;tG⁄)athe corresponding bit°dONLNd°HT5(p6in the °dONLNd®G5SQ)mode°dONLNd¨HQT¨) parameter was set.
  4682. °dONLNd¿l{k(ó6 SetStylScrap
  4683. °dONLNdŒá<ìÄ+$6PROCEDURE SetStylScrap(rangeStart, rangeEnd : LongInt;°dONLNd    í®û¬+l /     newStyles : StScrpHandle; hTE : TEHandle);
  4684. °dONLNd9©µl(“6 SetStylScrap°dONLNdE™l∂¥)T performs the °dONLNdS™¥∂)Hopposite function of °dONLNdh©µs)k GetStylScrap°dONLNdt™s∂õ)T.  The °dONLNd{©õµ⁄)(    newStyles°dONLNdÖ∂¬P(fi6Dparameter is a handle to a style scrap record which will be applied °dONLNd…∂P¬⁄(finover the given range of text.°dONLNdË√œ-(Î6The °dONLNdÏ√-œ˚),current selection range is not changed.  If °dONLNd¬˚Œ:)Œ    newStyles°dONLNd!√:œJ)? is °dONLNd%¬JŒ_)NIL°dONLNd(√_œq) or °dONLNd,¬qŒÜ)hTE°dONLNd/√Üœ⁄) is a handle to an°dONLNdB–‹C(¯6
  4685. old style °dONLNdLœC€{)+TERecord°dONLNdT–{‹Ç)8, °dONLNdVœÇ€÷) SetStylScrap°dONLNdb–÷‹)T does nothing.°dONLNdqËÙl(6 SetStylScrap°dONLNd}ÈlıÛ)T will terminate without error °dONLNdõÈÛı⁄)á1if it prematurely reaches the end of the range or°dONLNdÕıú(6Vif there are not enough scrap style elements to cover the whole range.  In the latter °dONLNd#ıú⁄(∫case, the last°dONLNd2
  4686. ^()6Hstyle in the scrap record will be applied to the remainder of the range.
  4687. °dONLNd{%4r*' TENumStyles
  4688. °dONLNdà@<Lt+$4FUNCTION TENumStyles(rangeStart, rangeEnd : LongInt;°dONLNd¡K®WV+l    hTE : TEHandle) : LongInt;
  4689. °dONLNdflbn0(ä6This °dONLNd‰b0n‚)%function returns the number of style °dONLNd    b‚n)≤changes°dONLNdbn⁄)&+ contained in the given range, counting one°dONLNd<nz)(ñ6for °dONLNd@n)z⁄)[the start of the range.  Note that this does not necessarily represent the number of unique°dONLNdúzÜE(¢6@styles for the range, because some styles may be repeated.  For °dONLNd‹zEÜ⁄(¢c old-style TextEdit records, this°dONLNd˝Üíî(Æ6function always returns 1. ◊4◊˘
  4690. *>4) of 7(ÏY%Styled TextEdit Changes in System 6.0ˇ™◊#ˇ ˇˇˇˇ#◊ 
  4691. IR,Times
  4692. .+Z-Developer Support Center(-fi
  4693. December 1988 /X/
  4694. °dONLNd<)˘(EZXThis function is useful for calculating the amount of memory that would be required for °dONLNdX˘)˛(Ea°dONLNdZ*<6É(RZcontemplated _,
  4695. Courier°dONLNdh)É5¶)GTECut°dONLNdm*¶6º)# or _°dONLNdr)º5Ê)TECopy°dONLNdx*Ê6
  4696. )*    .  Since °dONLNdÅ*
  4697. 6˛)'4the style scrap record is linear in nature, with one°dONLNd∂7<Cç(_ZDelement for each style change, you can multiply the result returned °dONLNd˙7çCü(_´by °dONLNd˝6üBÏ) TENumStyles°dONLNd7ÏC˛)M by°dONLNd C<Oœ(lZSizeOf(ScrpSTElement)°dONLNd!DœPÍ)ì; and add 2 to get the amount of memory that will be needed.
  4698. °dONLNd]h<w£(ìZ TECustomHook
  4699. °dONLNdkÉ`èº+$:PROCEDURE TECustomHook(which : TEHook; VAR addr : ProcPtr;°dONLNd™éÃöJ+l      hTE : TEHandle);
  4700. °dONLNd¿•<±à(ÕZThis procedure °dONLNdœ•à±˛)LMlets applications customize the functions of TextEdit by setting the TextEdit°dONLNd≤<æ¥(⁄Zbottleneck routines.  The °dONLNd7±¥Ω◊)xwhich°dONLNd<≤◊æˆ)#> parameter specifies which bottleneck routine to replace, and °dONLNdz≤ˆæ˛(⁄is°dONLNd}ø<Àd(ÁZof type °dONLNdÖæd é)(TEHook°dONLNdãøéÀ)* (described below).  When °dONLNd•æ m)ã TECustomHook°dONLNd±ømÀØ)T returns, the °dONLNdøæØ À)Baddr°dONLNd√øÀÀ–) °dONLNdƒø–À˛)    parameter°dONLNdŒÃ<ÿw(ÙZ
  4701. contains the °dONLNd€ÃwÿÉ);8address of the previous bottleneck routine specified by °dONLNdÀÉ◊¶(Ù°which°dONLNdöÿ˛)#.  This is returned°dONLNd,ÿ<‰ (Z1so that bottleneck routines can be daisy-chained.
  4702.     °dONLNd_`˚t+$TYPE°dONLNdf˙Ñ…+$
  4703. ATEHook = (intEOLHook, intDrawHook, intWidthHook, intHitTestHook);
  4704. °dONLNd®<æ(9ZThe internally used fields, °dONLNdƒæ˝)Ç    recalBack°dONLNdÕ˝)? and °dONLNd“\)
  4705. recalLines°dONLNd‹\¿)F now form a handle °dONLNdÔ¿˛)dto the list of°dONLNd˛<*Õ(FZTextEdit bottleneck routines. °dONLNdÕ*)ë Each °dONLNd")()#TERecord°dONLNd*(*˛)8* has its own set of bottleneck routines to°dONLNdU+<7¯(SZ&provide for maximum flexibility.  The °dONLNd{*¯6L)º TECustomHook°dONLNdá+L7ı)T! procedure should always be used °dONLNd®+ı7˛)©to°dONLNd´7<Cü(_ZMchange the bottleneck routines instead of modifying the edit record directly.°dONLNd˘P<\B*:Also, it is important to note that you should not clone a °dONLNd3OB[e(x`TERec°dONLNd8Pe\l)#. °dONLNd:Pl\˛) Doing so would duplicate the°dONLNdX]<i_(ÖZhandle °dONLNd_]_iè)#
  4706. stored in °dONLNdi\èhŒ)0    recalBack°dONLNdr]ŒiÈ)? and °dONLNdw\Èh/)
  4707. recalLines°dONLNdÅ]/i˛)F'.  When one of the TextEdit records was°dONLNd©i<u (ëZSdisposed, the handle stored in the copy would be invalid, and TextEdit would crash.°dONLNd˝Ç<é≈*There are four bottleneck °dONLNdÇ≈é˜)â
  4708. routines, °dONLNd!Řç6)2    TEEOLHook°dONLNd*Ç6éB)?, °dONLNd,ÅBçè) TEWidthHook°dONLNd7Çèéõ)M, °dONLNd9Åõç·)
  4709. TEDrawHook°dONLNdCÇ·é˛)F, and°dONLNdIé<öó(∑Z
  4710. TEHitTestHook°dONLNdVèóõò)[6, described individually below.  When replacing these °dONLNdåèòõ˛(∑∂routines, note that all°dONLNd§ú<®∫(ƒZPregisters except those specified as containing return values must be preserved. °dONLNdÙú∫®(ƒÿ  Registers °dONLNdˇõ߲)6A3°dONLNd©<µP(—Zand °dONLNd®P¥^)A4°dONLNd©^µŒ) contain a pointer and a °dONLNd!©Œµ˛)pAhandle to the TextEdit record respectively.  Line start positions°dONLNdc∂<¬≥(fiZcan be obtained from the °dONLNd|µ≥¡˘)w
  4711. lineStarts°dONLNdÜ∂˘¬j)F array in the edit record.°dONLNd°œ<€,(˜Z3None of these bottleneck routines are called from _°dONLNd‘Œ,⁄])TextBox°dONLNd€œ]€a)1.
  4712. °dONLNd›Û<ë(Z    TEEOLHook
  4713. °dONLNdÁ<≥*SThis routine tests a given character and returns with the appropriate status flags °dONLNd:≥˛(6—set in the status°dONLNdL<'{(CZFregister.  The default action is to merely compare the character with °dONLNdí{&ê(Cô$0D°dONLNdïê'ì) °dONLNdñì'˛)(a carriage return) and°dONLNdÆ'<3\(OZreturn.°dONLNd∂?<Kh*    On entry:°dONLNd¿?ÑKí)HD0°dONLNd√?®K    )$character to compare°dONLNd⁄?\Kx)¥(byte)°dONLNd„KÑWí(s¢A3°dONLNdÊK®W2)$pointer to the TextEdit record°dONLNd    K\Wy)¥(long)°dONLNd    WÑcí(¢A4°dONLNd    W®c0)$handle to the TextEdit record°dONLNd    1W\cy)¥(long)°dONLNd    8o<{a(óZOn exit:°dONLNd    Bo®{é)l4z flag clear if end-of-line character, set otherwise ◊X◊
  4714. (ÏZ%Styled TextEdit Changes in System 6.0(Ï5) of 7ˇÇ◊#ˇ ˇˇˇˇ#◊ 
  4715. IR,Times
  4716. .+6-Macintosh Technical Notes /4/˘
  4717. °dONLNd)8v*' TEWidthHook
  4718. °dONLNd DP0*This °dONLNdD0P⁄)Yroutine is called any time the width of various components of a line are calculated.  The°dONLNdkP\n(x6Lappropriate font, face, and size characteristics have already been set into °dONLNd∑Pn\⁄(xåthe current port by the°dONLNdœ]i(Ö6=time this routine is called.  The default action is to call _,
  4719. Courier°dONLNd \hd(Ö<
  4720. Char2Pixel°dONLNd]diõ)F  and return.°dONLNd#vÇD(û6    On entry:°dONLNd-u`Ån)HD0°dONLNd0vÑǯ)$length of text to measure°dONLNdKv8ÇY)¥(word)°dONLNdTÇ`én(´~D1°dONLNdWÉÑè»)$offset into text°dONLNdjÉ8èY)¥(word)°dONLNdsè`õn(∏~A0°dONLNdvêÑú˚)$pointer to text to measure°dONLNdíê8úU)¥(long)°dONLNdõú`®n(≈~A3°dONLNdûùÑ©)$pointer to the TextEdit record°dONLNdæù8©U)¥(long)°dONLNd«©`µn(“~A4°dONLNd ™Ñ∂ )$handle to the TextEdit record°dONLNdÈ™8∂U)¥(long)°dONLNd√œ=(Î6On exit:°dONLNd˘¬`Œn)HD1°dONLNd¸√Ñœ)$width of measured text°dONLNd√8œY)¥(word)
  4721. °dONLNdÁˆr(6
  4722. TEDrawHook
  4723. °dONLNd&b*EThis routine is called any time the various components of a line are °dONLNdkb⁄(*Ädrawn.  The appropriate°dONLNdÉ∞(66Xfont, face, and size characteristics have already been set into the current port by the °dONLNd€∞⁄(6Œ    time this°dONLNdÂ'Û(C63routine is called.  The default action is to call _°dONLNdÛ&+)€DrawText°dONLNd +'b)8  and return.°dONLNd-4@D(\6    On entry:°dONLNd73`?n)HD0°dONLNd:4Ñ@»)$offset into text°dONLNdM48@Y)¥(word)°dONLNdV@`Ln(i~D1°dONLNdYAÑMÈ)$length of text to draw°dONLNdrA8MY)¥(word)°dONLNd{M`Yn(v~A0°dONLNd~NÑZÏ)$pointer to text to draw°dONLNdóN8ZU)¥(long)°dONLNd†Z`fn(É~A3°dONLNd£[Ñg)$pointer to the TextEdit record°dONLNd√[8gU)¥(long)°dONLNdÃg`sn(ê~A4°dONLNdœhÑt )$handle to the TextEdit record°dONLNdÓh8tU)¥(long)
  4724. °dONLNdıåõ~(∑6
  4725. TEHitTestHook
  4726. °dONLNdß≥-*>This routine is called to determine the character position in °dONLNdAß-≥⁄(œK&a line given the horizontal offset, in°dONLNdh¥¿U(‹6
  4727. pixels, from °dONLNdu¥U¿[)=9the beginning of a line.  The default action is to call _°dONLNdÆ≥[ø°(‹y
  4728. Pixel2Char°dONLNd∏¥°¿⁄)F  and return.°dONLNdΔ¡Õ®(È6For more information, see the °dONLNd‰¡®ÕÙ)êdescription of _°dONLNdÙ¿ÙÃ:)L
  4729. Pixel2Char°dONLNd˛¡:Õ⁄)F! in the Script Manager chapter of°dONLNd ÕŸj(ı6Inside Macintosh°dONLNd0ÕjŸ±)RB, Volume 5 and the Inside Macintosh Interim Chapter Draft, Script °dONLNdrÕ±Ÿ⁄(ıœManager°dONLNdzŸÂ,(62.0.°dONLNdÚ˛D*    On entry:°dONLNdâÒ`˝n)HD0°dONLNdåÚÑ˛)$length of text to hit test°dONLNd®Ú8˛Y)¥(word)°dONLNd±˛`
  4730. n('~D1°dONLNd¥ˇÑ  )$pixel offset from start of text°dONLNd’ˇ8 Y)¥(word)°dONLNdfi `n(4~A0°dONLNd· ÑÈ)$pointer to start of text°dONLNd¸ 8U)¥(long)°dONLNd`$n(A~A3°dONLNdÑ%)$pointer to the TextEdit record°dONLNd(8%U)¥(long)°dONLNd1%`1n(N~A4°dONLNd4&Ñ2 )$handle to the TextEdit record°dONLNdS&82U)¥(long)°dONLNdZ?K=(g6On exit:°dONLNdc>`Jn)HD0°dONLNdf?ÑKˆ)$pixel width to last offset°dONLNdÇ?8Kn)¥
  4731. (low word)°dONLNdêKÑW(s¢Boolean = TRUE if a character°dONLNdÆK8Wq)¥ (high word)°dONLNdΩWÑct(¢2offset corresponding to the pixel width was found.°dONLNdÚc`on(å~D1°dONLNdıdÑpÃ)$character offset°dONLNdd8pY)¥(word)°dONLNdp`|n(ô~D2°dONLNdqÑ} )$Boolean = TRUE if the pixel°dONLNd1q8}Y)¥(word)°dONLNd;}Ñâ_(•¢3offset falls within the left side of the character. ◊4◊˘
  4732. (Ï66) of 7(ÏY%Styled TextEdit Changes in System 6.0ˇ‰◊#ˇ ˇˇˇˇ#◊ 
  4733. IR,Times
  4734. .+Z-Developer Support Center(-fi
  4735. December 1988 /X/
  4736. °dONLNd<,‚(HZTextEdit Data Structures
  4737. °dONLNd8<DÎ*SThe illustration on the following page is a graphic representation of the TextEdit °dONLNdl8ÎD˛(`    data°dONLNdqD<P€(lZVstructures.  You should use this information only for debugging and so you understand °dONLNd«D€P˛(l˘what is°dONLNdœP<\p(xZ going on.  °dONLNd⁄Pp\˛)4SFor reading or writing these data structures, the TextEdit routines should be used.°dONLNd.\<h(ÑZ+This will help ensure future compatibility.°dONLNdZå<ò¶*0Further Reference: ∑X∑°dONLNdmôN•R+
  4738. •°dONLNdoô`•fi)M.OV.GestaltSysenvirons ◊X◊
  4739. (ÏZ%Styled TextEdit Changes in System 6.0(Ï7) of 7ˇ t◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  4740. /ZÅ#
  4741.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4742. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4743. .WIQkWIQk+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4744. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4745. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4746.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4747. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  4748. IR.°dONLNd{<é¨(®Z TEScroll Bug
  4749. °dONLNd
  4750. ç<úZ*Text°dONLNdç}ú˛(∏õM.TE.TEScrollBug
  4751. °dONLNd$®<¥t(–Z Revised by:°dONLNd1®≈¥˛(–„
  4752. March 1988°dONLNd<¥<¿q(‹Z Written by:°dONLNdH¥Ñ¿«)H
  4753. Bryan Stearns°dONLNdV¥À¿˛(‹È
  4754. April 1986 ÎXΰdONLNda⁄<Ê5(Z2A bug in TextEdit causes the following problem: a °dONLNdì⁄5ÊX)˘call to ,
  4755. Courier°dONLNdõŸXÂê)#TEScroll°dONLNd£⁄êÊ˛)8 with no horizontal or°dONLNd∫Á<ÛÍ(Z%vertical displacement (that is, both °dONLNdflÊÍÚ¯)Ædh°dONLNd·Á¯Û) and °dONLNdÊÊÚ!)dv°dONLNdËÁ!ÛF) set to °dONLNdÁFÛ˛)%%zero) results in disappearance of the°dONLNdÛ<ˇ(ZEinsertion point. Since such calls do nothing, they should be avoided:
  4756.     °dONLNd] `Ç+$:IF (dh <> 0) OR (dv <> 0) THEN TEScroll(dh,dv,myTEHandle);
  4757. °dONLNdò9<E¶(aZFurther Reference: dXd°dONLNd´FNRR+
  4758. •°dONLNd≠F`Rà)TextEdit°dONLNd∂RN^R(zl•°dONLNd∏R`^¡)M.TE.TextEditBugs ◊X◊
  4759. (ÏZ TEScroll Bug(Ï1) of 1ˇ°¿Ù%%DSIDICT:_cv
  4760. currentdict /bu known {bu}if
  4761. userdict /_cv known not{userdict /_cv 30 dict put}if
  4762. _cv begin
  4763. /bdf{bind def}bind def
  4764. currentscreen/cs exch def/ca exch def/cf exch def
  4765. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4766. /ss{//cf //ca //cs setscreen}bdf
  4767. /stg{ss setgray}bdf
  4768. /strgb{ss setrgbcolor}bdf
  4769. /stcmyk{ss cvcmyk}bdf
  4770. /min1{dup 0 eq{pop 1}if}bdf
  4771. end
  4772. currentdict /bn known {bn}if
  4773. †ø◊#ˇ ˇˇˇˇ#◊†Ç 
  4774. /ZÅ#
  4775.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4776. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4777. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4778. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4779. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4780.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4781. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  4782. IR.°dONLNdz<ç%(ßZTextEdit: Advice & Descent
  4783. °dONLNdå<õZ*Text°dONLNd!åkõ˛(∑âM.TE.TextEditAdvice
  4784. °dONLNd5ß<≥t(œZ Revised by:°dONLNdBß≈≥˛(œ„
  4785. March 1988°dONLNdM≥<øq(€Z Written by:°dONLNdY≥Ñø¥)H
  4786. Rick Blair°dONLNdd≥Õø˛(€Π   June 1986°dONLNdnÀ<◊Ù(ÛZYThis technical note will point out some bugs (and possible workarounds), and other items °dONLNd«ÀÙ◊˛(Ûof°dONLNd ◊<„Ï(ˇZ%interest for the TextEdit programmer. X°dONLNd¸<w*%    TESelRect°dONLNd˙< ‹*#Multiple line selections are often °dONLNd‹ ˛)†:more complex shapes than simple rectangles. If this is the°dONLNdX!<-l(IZ
  4787. case, the ,
  4788. Courier°dONLNdb l,´)0    teSelRect°dONLNdk!´-Ï)? field of the °dONLNdy Ï,)ATERec°dONLNd~!-A)#  is set to °dONLNdâ!A-˛)2&the last (bottommost) rectangle in the°dONLNd∞.<:Å(VZselection. The °dONLNdø-Å9π)EteHiHook°dONLNd«.π:Ü)80 is called to invert each line of the selection.°dONLNd¯G<S»(oZThe ROM limits the selection °dONLNdG»Sx)å(range (i.e. the lines that get set into °dONLNd=FxR∑)∞    teSelRect°dONLNdFG∑S˛)?) to only those°dONLNdVT<`√(|Zlines which will fit into the °dONLNdtS√_˚)áviewRect°dONLNd|T˚`S)8. This means that °dONLNdéSS_í)X    teSelRect°dONLNdóTí`Œ)? will be left °dONLNd•TŒ`˛)< at the last°dONLNd±`<l≈(àZNvisible line. (The old 64K ROMs made all the calls for the complete selection °dONLNdˇ`≈l˛(à„ and just let°dONLNd l<x»(îZ clipping take care of the rest.)°dONLNd-ê<úu*$TEDoText°dONLNd6©<µõ*KThe parameters of this special hook into TextEdit need a little additional °dONLNdÅ©õµ⁄(—π
  4789. explanation. °dONLNdé®⁄¥Ë)?D3°dONLNdê©Ëµ˛) and°dONLNdïµ<¡J(fiZD4°dONLNdó∂J¬b) are °dONLNdú∂b¬Î)described on page 391 of °dONLNdµ∂άt)âInside Macintosh Volume I°dONLNdŒ∂t¬˛)â as being the first and last°dONLNdÎ√<œX(ÎZ?characters to be redrawn. This is true but specific to the –1 “°dONLNd*¬XŒÇ(ÎvDoDraw°dONLNd0√ÇœÈ)*” case. In fact, all the °dONLNdI√Èœ˛)gcalls°dONLNdO–<‹J(¯Zto °dONLNdRœJ€Ç)TEDoText°dONLNdZ–Ç‹i)82 are interested in these first and last character °dONLNdå–i‹˛)Ápositions. They determine the°dONLNd™›<Èq(ZBselection for a (1) highlight call, the caret position for a (–2) °dONLNdÏ‹qË¢(èDoCaret°dONLNdÛ›¢È‚)1
  4790.  call (where °dONLNd‹‚Ë)@D4°dONLNd›È˛) is°dONLNdÍ<ˆ÷(Z!ignored as it’s assumed to equal °dONLNd'È÷ı‰)öD3°dONLNd)͉ˆ)), etc.°dONLNd1<~(+ZNote that the °dONLNd?~Ø)BDoCaret°dONLNdFØ    )1 (–2) call behaves °dONLNdY    ò)Zdifferently than described in °dONLNdwòÎ)èInside Macintosh°dONLNdáβ)S, as°dONLNdå<)(7Z,well. Good old page 391 says it sets up the °dONLNd∏)˛)Ì(pen position for caret drawing. Since an°dONLNd·<'Ç(DZ
  4791. InvertRect°dONLNdÎÇ(s)F7 call is used to draw the caret if you use the default °dONLNd"s'≤)Ò    teCarHook°dONLNd+≤( )?, the °dONLNd1 (˛)    ROMs just°dONLNd;)<5[(QZset up °dONLNdB([4ö)    teSelRect°dONLNdK)ö5l)?+, they don’t bother with the QuickDraw pen.°dONLNdwA<Mç(iZ TEScrpLength°dONLNdÑZ<fø*Inside Macintosh describes °dONLNdüYøe)É TEScrpLength°dONLNd´Zfè)T as a long integer; indeed, °dONLNd«Zèf˛)|four bytes are reserved°dONLNdflf<r¶(éZfor this value with the °dONLNd˜f¶r˛)jCintent of someday using that range of values. However, the ROMs use°dONLNd;s<Á(õZ%word operations in their accesses to °dONLNd`rÁ~;)´ TEScrpLength°dONLNdls;È)T% and make word calculations with it. °dONLNdësÈ˛)ÆThis°dONLNdñÄ<å…(®Zmeans that the high word of °dONLNd≤…ã)ç TEScrpLength°dONLNdæÄåò)T is used for calculations. °dONLNdŸÄòå˛){This is something to°dONLNdÓå<ò(¥Zwatch out for. ◊X◊
  4792. *8TextEdit: Advice & Descent(Ï1) of 2ˇ°¿Ù%%DSIDICT:_cv
  4793. currentdict /bu known {bu}if
  4794. userdict /_cv known not{userdict /_cv 30 dict put}if
  4795. _cv begin
  4796. /bdf{bind def}bind def
  4797. currentscreen/cs exch def/ca exch def/cf exch def
  4798. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4799. /ss{//cf //ca //cs setscreen}bdf
  4800. /stg{ss setgray}bdf
  4801. /strgb{ss setrgbcolor}bdf
  4802. /stcmyk{ss cvcmyk}bdf
  4803. /min1{dup 0 eq{pop 1}if}bdf
  4804. end
  4805. currentdict /bn known {bn}if
  4806. †ø
  4807. ™◊#ˇ ˇˇˇˇ#◊ 
  4808. IR,Times
  4809. .+6-Macintosh Technical Notes /4/˘
  4810. °dONLNd)5U*$    CharWidth°dONLNd
  4811. BNn*Inside Macintosh°dONLNdBnN¨)V  says that ,
  4812. Courier°dONLNd%A¨MÎ)>    CharWidth°dONLNd.BÎNÛ)? °dONLNd/BÛN⁄),takes stylistic variations into account when°dONLNd\O[S(w6 determining °dONLNdhOS[);'the width of a character. In fact, for °dONLNdèO[)≥italic°dONLNdïO[5) and °dONLNdöN5\c)outlined°dONLNd¢Oc[⁄). styles the extra width is°dONLNdΩ]i‹(Ö6+not taken into account. TextEdit relies on °dONLNdË\‹h)ƒ    CharWidth°dONLNdÒ]i)? °dONLNdÚ]i⁄))for positioning of the caret, etc. If you°dONLNdiuÃ(ë6`have chosen to use, for instance, italic style in your TE record you will find that as you type °dONLNd|iÃu⁄(ëÍthe°dONLNdÄuÅÂ(ù6-caret actually overlaps the character to the °dONLNd≠uÂÅ⁄)Õ1left and so when the caret is erased some of that°dONLNdflÅç…(©6(character will get erased, too. This is °dONLNdÅ…ç⁄)±7somewhat disconcerting to the user but the program will°dONLNd?çôÉ(µ6still function correctly.°dONLNdY±ΩO*$    Clikloops°dONLNdc…’±*SIf you add your own click loop and try to do something like update scroll bars you °dONLNd∂…±’⁄(Òœmay run°dONLNdæ’·Ã(˝6\into trouble. Before your routine gets called, TextEdit will have set clipping down to just °dONLNd’÷⁄(˝Íthe°dONLNd·ÌP(
  4813. 6viewRect°dONLNd&‚PÓˇ)8%. You will have to save away the old °dONLNdK‚ˇÓ‘)Ø0clipping region, set it out to sufficient size (°dONLNd{‚‘Ó⁄)’–°dONLNd|Ó˙>(632767, °dONLNdÉÓ>˙⁄)&N–32767, 32767, 32767 is probably OK), do your drawing, then restore TextEdit’s°dONLNd“˙Î("6/clipping area so that it can function properly.°dONLNd*6Ç*0Further Reference: U4U˘°dONLNd7*C.+
  4814. •°dONLNd7<Cd)TextEdit°dONLNd C*O.(kH•°dONLNd"C<Oö)M.TE.TEScrollBug°dONLNd3O*[.(wH•°dONLNd5O<[§)M.TE.EOLAmbiguity°dONLNdG[*g.(ÉH•°dONLNdI[<gù)M.TE.TextEditBugs ◊4◊˘
  4815. (Ï62) of 2(ÏàTextEdit: Advice & DescentˇÍ◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  4816. /ZÅ#
  4817.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4818. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4819. .WIQkWIQk+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4820. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4821. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4822.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4823. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  4824. IR.°dONLNd{<é*(®ZTextEdit Bugs in System 4.2
  4825. °dONLNdç<úZ*Text°dONLNd"çyú˛(∏óM.TE.TextEditBugs
  4826. °dONLNd4®<¥t(–Z Revised by:°dONLNdA®≈¥˛(–„
  4827. March 1988°dONLNdL¥<¿q(‹Z Written by:°dONLNdX¥Ñ¿≈)H
  4828. Chris Derossi°dONLNdf¥ ¿˛(‹Ë
  4829.  June 1987°dONLNdqÃ<ÿö(ÙZThis note formerly °dONLNdÑÃöÿ˛)^Edescribed the known bugs with the version of Styled TextEdit that was°dONLNd ÿ<‰Ê(Zprovided with System 4.1. Many °dONLNdÈÿʉ˛)™4of these bugs were fixed in System 4.2. This updated°dONLNd‰<L( Z6Technical Note describes the remaining known problems. X
  4830. °dONLNdU<$ë*4 TEStylInsert
  4831. °dONLNdb1<=a*Calling ,
  4832. Courier°dONLNdj0a<µ)% TEStylInsert°dONLNdv1µ==)T while the TextEdit record is °dONLNdî1==˛)à)deactivated causes unpredictable results,°dONLNdæ><J¥(fZso make sure to only call °dONLNdÿ=¥I)x TEStylInsert°dONLNd‰>JØ)T$ when the TextEdit record is active.
  4833. °dONLNd    b<qÖ(çZ
  4834. TESetStyle
  4835. °dONLNd~<äx* When using °dONLNd~xää)<the °dONLNd#}äâ¥)doFace°dONLNd)~¥äÔ)*  mode with °dONLNd4}Ôâ5);
  4836. TESetStyle°dONLNd>~5ä˛)F+, the style that you pass as a parameter is°dONLNdjä<ñX(≥ZORed°dONLNdnãXóE)7 into the style of the currently selected text. If you °dONLNd•ãEó˛)Ì&pass the empty set (no styles) though,°dONLNdÃó<£Ç(¿Z
  4837. TESetStyle°dONLNd÷òǧ[)F+ is supposed to remove all styles from the °dONLNdò[§∏)Ÿselected text. But °dONLNdó∏£˛)]
  4838. TESetStyle°dONLNd•<±C(ÕZ5checks an entire word instead of just the high-order °dONLNdT•C±Å(Õa byte of the °dONLNd`§Å∞´)>tsFace°dONLNdf•´±˛)* field. The style°dONLNdx±<Ωy(ŸZDinformation is contained completely in the high-order byte, and the °dONLNdº±yΩ˛(Ÿólow-order byte may contain°dONLNd◊Ω<…e(ÂZgarbage.°dONLNd‡÷<‚‘*"If the low-order byte isn’t zero, °dONLNd’‘·)ò
  4839. TESetStyle°dONLNd ÷‚=)F thinks °dONLNd÷=‚d)#    that the °dONLNd’d·é)'tsFace°dONLNd#÷邲)* field isn’t empty, so it°dONLNd=‚<ÓG(
  4840. Z6goes ahead and ORs it with the selected text’s style. °dONLNds‚GÓ˛(
  4841. e%Since the actual style portion of the°dONLNdôÓ<˙f(ZtsFace°dONLNdüÔf˚É)* field °dONLNd¶ÔÉ˚∏)=is zero, no change occurs with the text. If you want to have °dONLNd„Ó∏˙˛(÷
  4842. TESetStyle°dONLNdÓ¸<H($Z<remove all styles from the text, you can explicitly set the °dONLNd*˚Hr($ftsFace°dONLNd0¸rÿ)* field to zero like this:
  4843.     °dONLNdK`o(;~VAR°dONLNdP`)ÿ*
  4844.    myStyle  : TextStyle;°dONLNdj(`3”*
  4845.    anIntPtr : ^Integer;°dONLNdÉ<`Gy*BEGIN°dONLNdäF`Q~*
  4846.    ...°dONLNdíP`[˚*
  4847.    anIntPtr := @myStyle.tsFace;°dONLNd≥Z`e∫*
  4848.    anIntPtr^ := 0;°dONLNd«d`o<*
  4849. ,   TESetStyle(doFace, myStyle, TRUE, textH);°dONLNdın`y~*
  4850.    ...°dONLNd˝x`Ét*
  4851. END; ◊X◊
  4852. (ÏZTextEdit Bugs in System 4.2(Ï1) of 2ˇ°¿Ù%%DSIDICT:_cv
  4853. currentdict /bu known {bu}if
  4854. userdict /_cv known not{userdict /_cv 30 dict put}if
  4855. _cv begin
  4856. /bdf{bind def}bind def
  4857. currentscreen/cs exch def/ca exch def/cf exch def
  4858. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4859. /ss{//cf //ca //cs setscreen}bdf
  4860. /stg{ss setgray}bdf
  4861. /strgb{ss setrgbcolor}bdf
  4862. /stcmyk{ss cvcmyk}bdf
  4863. /min1{dup 0 eq{pop 1}if}bdf
  4864. end
  4865. currentdict /bn known {bn}if
  4866. †ø◊#ˇ ˇˇˇˇ#◊ 
  4867. IR,Times
  4868. .+6-Macintosh Technical Notes /4/˘
  4869. °dONLNd)8c*'    TEStylNew
  4870. °dONLNd
  4871. EQ
  4872. *5The line heights array does not get initialized when ,
  4873. Courier°dONLNd?D
  4874. PI)Ú    TEStylNew°dONLNdHEIQW)? is °dONLNdLEWQ⁄)called. Because of this, the°dONLNdiR^ô(z6caret is initially drawn in °dONLNdÖRô^õ)Å2a random height. This is easily solved by calling °dONLNd∑Qõ]⁄(zπ    TECalText°dONLNd¡_kö(á6immediately after calling °dONLNd€^öjŸ)Ç    TEStylNew°dONLNd‰_Ÿk0)?. Extra calls to °dONLNdı^0jo)W    TECalText°dONLNd˛_okñ)? don’t °dONLNd_ñk⁄)'
  4875. hurt anything°dONLNdkw"(ì67anyway, so this will be compatible with future Systems.°dONLNdKÉè©*WAn extra character run is placed at the beginning of the text which corresponds to the °dONLNd¢É©è⁄(´« font, size,°dONLNdÆêúÎ(∏6*and style which were in the grafPort when °dONLNdÿèÎõ*)”    TEStylNew°dONLNd·ê*úh)?
  4876.  was called. °dONLNdÓêhú⁄)>This can cause the line°dONLNdù©&(≈6?height for the first line to be too large. To avoid this, call °dONLNdEú&®^(≈DTextSize°dONLNdMù^©⁄)8 with the desired text size°dONLNdi™∂](“6before calling °dONLNdx©]µú)E    TEStylNew°dONLNdÅ™ú∂5)?". If the text’s style information °dONLNd£™5∂⁄)ô cannot be determined in advance,°dONLNdƒ∑√B(fl6
  4877. then call °dONLNdŒ∂B¬z)*TextSize°dONLNd÷∑z√=)8, with a small value (like 9) before calling °dONLNd∂=¬|)√    TEStylNew°dONLNd ∑|√Ä)?.
  4878. °dONLNd
  4879. €ÍT(6TEScroll
  4880. °dONLNd˜8*6The bug documented in M.TE.TEScrollBug remains in the °dONLNdL˜8Ç(Vnew TextEdit. °dONLNdZˆÇ∫)JTEScroll°dONLNdb˜∫⁄)8 called°dONLNdjS(+6Dwith zero for both vertical and horizontal displacements causes the °dONLNdÆS⁄(+qinsertion point to disappear.°dONLNdÃO(86>The workaround is the same as before; check to make sure that °dONLNd
  4881. O](8mdV°dONLNd ]v) and °dONLNdvÑ)dH°dONLNdÑΔ) are not both °dONLNd!Δ⁄)Bzero°dONLNd&)[(E6before calling °dONLNd5[(ì)CTEScroll°dONLNd=ì)ó)8.
  4882. °dONLNd?AP≈(l6Growing TextEdit Record
  4883. °dONLNdW]i(*8TextEdit is supposed to dynamically grow and shrink the °dONLNdè\(hn(ÖF
  4884. LineStarts°dONLNdô]ni©)F array in the °dONLNdß\©hÃ);TERec°dONLNd¨]Ãiœ)# °dONLNd≠]œi⁄)so°dONLNd∞iuö(ë6Tthat it has one entry per line. Instead, when lines are added, TextEdit expands the °dONLNdiöu⁄(ë∏
  4885. array without°dONLNduÅÉ(ù6first checking to see if °dONLNd+uÉÅ⁄)kHit’s already big enough. In addition, TextEdit never reduces the size of°dONLNdtÅçH(©6 this array.°dONLNdÄô•ô*Because of this, the longer °dONLNdúôô•⁄)ÅFa particular TextEdit record is used, the larger it will get. This can°dONLNd„¶≤(Œ64be particularly nasty in programs that use a single °dONLNd•±9)˛TERec°dONLNd¶9≤p)#
  4886.  for many °dONLNd&¶p≤⁄)7operations during the°dONLNd<≤æ}(⁄6program’s execution.
  4887. °dONLNdR÷¸*' Restoring Saved TextEdit Records
  4888. °dONLNdsÒ˝ê*Applications have used a °dONLNdåÒê˝⁄)xDtechnique for saving and restoring styled text which involves saving°dONLNd—˛
  4889. `(&6the contents of °dONLNd·˛`
  4890. [)H4all of the TextEdit record handles. When restoring, °dONLNd˝[    ö)˚    TEStylNew°dONLNd˛ö
  4891. ⁄)? is called and°dONLNd-
  4892. A(26>the TextEdit record’s handles are disposed. The saved handles °dONLNdk
  4893. A⁄(2_ are then loaded and put into the°dONLNdå#˙(?6.TextEdit record. This technique should not be °dONLNd∫˙#;)‚
  4894. used for the °dONLNd«;"z)A    nullStyle°dONLNd–z#⁄)? handle in the style°dONLNdÂ#/:(K6record.°dONLNdÌ<H^*Instead, when °dONLNd˚;^Gù)F    TEStylNew°dONLNd<ùHfi)? is called, the °dONLNd;fiG)A    nullStyle°dONLNd<HB)? handle °dONLNd%<BH⁄)%from the style record should be°dONLNdEHTÈ(p6.copied into the saved style record. This will °dONLNdsHÈT⁄)—5ensure that the fields in the null-style record point°dONLNd©T`U(|6to valid data. ◊4◊˘
  4895. *p2) of 2(ÏÉTextEdit Bugs in System 4.2ˇ◊#ˇ ˇˇˇˇ#◊†Ç 
  4896. /ZÅ#
  4897.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4898. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4899. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4900. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4901. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4902.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4903. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  4904. IR.°dONLNdn<Å"(õZTextEdit Conversion Utility
  4905. °dONLNdÄ<èZ*Text°dONLNd"Ädè˛(´ÇM.TE.TextEditConvert
  4906. °dONLNd7õ<ßt(√Z Revised by:°dONLNdDõ≈߲(√„
  4907. March 1988°dONLNdOß<≥q(œZ Written by:°dONLNd[ßÑ≥œ)HHarvey Alcabes°dONLNdjßÀ≥˛(œÈ
  4908. April 1985°dONLNduø<À©(ÁZIText sometimes must be converted between a Pascal string and “pure” text °dONLNdæø©À˛(Á«in a handle. This°dONLNd–À<◊/(ÛZ3note illustrates a way to do this using MPW Pascal. X°dONLNd<¸◊*%UText contained in TextEdit records sometimes must be passed to routines which expect °dONLNdY◊¸˛(ıa Pascal°dONLNdb¸<\($Z;string of type Str255 (a length byte followed by up to 255 °dONLNdù¸\˛($zcharacters). The following MPW°dONLNdº<±(0ZOPascal unit can be used to convert between TextEdit records and Pascal strings:,
  4909. Courier
  4910.     °dONLNd
  4911.  `+´+$UNIT TEConvert;°dONLNd4`?™*B   {General utilities for conversion between TextEdit and strings}°dONLNdbH`Sú*    INTERFACE°dONLNdp\`gF*.      USES MemTypes,QuickDraw,OSIntf,ToolIntf;°dONLNd†p`{á*;      PROCEDURE TERecToStr(hTE: TEHandle; VAR str: Str255);°dONLNd›z`Öæ*
  4912. F      {TERecToStr converts the TextEdit record hTE to the string str.}°dONLNd%Ñ`èØ*
  4913. C      {If necessary, the text will be truncated to 255 characters.}°dONLNdjò`£s*7      PROCEDURE StrToTERec(str: Str255; hTE: TEHandle);°dONLNd£¢`≠√*
  4914. G      {StrToTERec converts the string str to the TextEdit record hTE. }°dONLNdÏ∂`¡µ*   IMPLEMENTATION°dONLNdˇ `’á*;      PROCEDURE TERecToStr(hTE: TEHandle; VAR str: Str255);°dONLNd<fi`ȶ*         BEGIN°dONLNdLË`Û#*
  4915. '            GetIText(hTE^^.hText, str);°dONLNduÚ`˝°*
  4916.  
  4917.          END;°dONLNdÑ`s*7      PROCEDURE StrToTERec(str: Str255; hTE: TEHandle);°dONLNdΩ`%¶*         BEGIN°dONLNdÕ$`/√*
  4918. G            TESetText(POINTER(ORD4(@str) + 1), ORD4(length(str)), hTE);°dONLNd.`9°*
  4919.  
  4920.          END;°dONLNd%B`Mt*END.
  4921. °dONLNd*p<|¶(òZFurther Reference: õXõ°dONLNd=}NâR+
  4922. •°dONLNd?}`âw)5Macintosh Memory Management: An Introduction TextEdit ◊X◊
  4923. (ÏZTextEdit Conversion Utility(Ï1) of 1ˇ°¿Ù%%DSIDICT:_cv
  4924. currentdict /bu known {bu}if
  4925. userdict /_cv known not{userdict /_cv 30 dict put}if
  4926. _cv begin
  4927. /bdf{bind def}bind def
  4928. currentscreen/cs exch def/ca exch def/cf exch def
  4929. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4930. /ss{//cf //ca //cs setscreen}bdf
  4931. /stg{ss setgray}bdf
  4932. /strgb{ss setrgbcolor}bdf
  4933. /stcmyk{ss cvcmyk}bdf
  4934. /min1{dup 0 eq{pop 1}if}bdf
  4935. end
  4936. currentdict /bn known {bn}if
  4937. †øÇ◊#ˇ ˇˇˇˇ#◊°d WORDS †å°d WORDR…†Ç 
  4938. /ZÅ#
  4939.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4940. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4941. .WIQkWIQk+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4942. Ä({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4943. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4944.     l+&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4945. BÄ(Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É°dWORD†ç
  4946. IR.°dONLNd{<é (®ZTextEdit EOL Ambiguity
  4947. °dONLNdç<úZ*Text°dONLNdçnú˛(∏åM.TE.EOLAmbiguity
  4948. °dONLNd/®<¥t(–Z Revised by:°dONLNd<®≈¥˛(–„
  4949. March 1988°dONLNdG¥<¿q(‹Z Written by:°dONLNdS¥Ñ¿∑)H Rick Blair °dONLNd_¥Œ¿˛(‹ÏMay 1987,
  4950. Courier°dONLNdhÃ<ÿâ(ıZ TESetSelect°dONLNdsÕâŸì)M8 may be used to position the insertion point at the end °dONLNd´ÕìŸ˛(ı±of a line. There is an°dONLNd¬Ÿ<µ(ZQambiguity, though; should the insertion point appear at the end of the preceding °dONLNdŸµÂ˛(”line or the start°dONLNd%Â<ÒÁ(
  4951. Z\of the following one? It is possible to determine what will happen, as you are about to see. X°dONLNdÇ
  4952. <o*%BThere is an internal flag used by TextEdit to determine where the °dONLNdƒ
  4953. o˛(2çinsertion point at the end of a°dONLNd‰<#Ê(?Z'line appears. This flag is part of the °dONLNd Ê"%)™    clikStuff°dONLNd%#])? field in the °dONLNd"]"Ä)8TERec°dONLNd'Ä#˛)#. It is there mainly for the°dONLNdD$<0\(LZuse of °dONLNdK#\/ç) TEClick°dONLNdR$ç0¶)1, but °dONLNdX$¶0˝)it is also used by °dONLNdk#˝/J)W TESetSelect°dONLNdv$J0˛)M( (although it defaults to the right side°dONLNdü0<<ü(XZof the previous line).°dONLNd∂H<T∞*RThe following code can be used to force the insertion point to appear at the left °dONLNdH∞T˛(pŒof the following°dONLNdT<`](|Z?line when it is positioned at the end of a line; in MPW Pascal:
  4954.     °dONLNdZl`wµ+$TEDeactivate(tH);°dONLNdmv`ÅŒ*
  4955. tH^^.clikStuff := 255;°dONLNdÜv8Å∞)ÿ{position caret on left}°dONLNd†Ä`ã((ß~(TESetSelect(eolcharpos, eolcharpos, tH);°dONLNd…Ä8ãç)ÿ{ambiguous point}°dONLNd‹ä`ï´(±~TEActivate(tH);
  4956. °dONLNdφ<¨s(»Z    In MPW C:
  4957.     °dONLNd˜∏`√µ+$TEDeactivate(tH);°dONLNd
  4958. ¬`Õ”*
  4959. (**tH).clikStuff = 255;°dONLNd$¬8Õ∫)ÿ/*position caret on left*/°dONLNd@Ã`◊((Û~(TESetSelect(eolcharpos, eolcharpos, tH);°dONLNdiÃ8◊ó)ÿ/*ambiguous point*/°dONLNd~÷`·´(˝~TEActivate(tH);
  4960. °dONLNdéÏ<¯Í(Z%If you want to ensure that the caret °dONLNd≥Ïͯ˛)Æ9is on the right side (to which it normally defaults) then°dONLNd̯<√( Zsubstitute a zero for the 255.°dONLNd (<4¶*0Further Reference: SXS°dONLNd5NAR+
  4961. •°dONLNd!5`A±)Inside Macintosh°dONLNd15±Ae)Q$, Volume V, Compatibility Guidelines°dONLNdVANMR(il•°dONLNdXA`Mfi)M.OV.GestaltSysenvirons ◊X◊
  4962. (ÏZTextEdit EOL Ambiguity(Ï1) of 1ˇ°¿Ù%%DSIDICT:_cv
  4963. currentdict /bu known {bu}if
  4964. userdict /_cv known not{userdict /_cv 30 dict put}if
  4965. _cv begin
  4966. /bdf{bind def}bind def
  4967. currentscreen/cs exch def/ca exch def/cf exch def
  4968. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  4969. /ss{//cf //ca //cs setscreen}bdf
  4970. /stg{ss setgray}bdf
  4971. /strgb{ss setrgbcolor}bdf
  4972. /stcmyk{ss cvcmyk}bdf
  4973. /min1{dup 0 eq{pop 1}if}bdf
  4974. end
  4975. currentdict /bn known {bn}if
  4976. †øÜ◊#ˇ ˇˇˇˇ#◊†Ç 
  4977. /ZÅ#
  4978.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  4979. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  4980. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  4981. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  4982. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  4983.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  4984. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  4985. IR.°dONLNdz<ç£(ßZ*TextEdit Record Size Limitations Revisited
  4986. °dONLNd+å<õZ*Text°dONLNd1ådõ˛(∑ÇM.TE.RecordSizeLimit
  4987. °dONLNdFß<≥q(œZ Written by:°dONLNdRßÑ≥æ)H
  4988. Mary Walsh°dONLNd]ßÕ≥˛(œΠ   June 1989°dONLNdgø<À”(ÁZOThis Technical Note describes another limit on the length of a TextEdit record °dONLNd∂ø”À˛(ÁÒthat was°dONLNdøÀ<◊∫(ÛZpreviously undocumented. X°dONLNdÿ<¸∫*%The TextEdit chapters in °dONLNdÒ∫¸
  4989. )~Inside Macintosh°dONLNd
  4990. ¸÷)S' document the 32K character limit on a °dONLNd(÷¸˛)…TextEdit°dONLNd1¸<"($Z.record length.  They do not, however, discuss °dONLNd_¸"˛)Ê-the more subtle constraint on the size of the,
  4991. Courier°dONLNdç<t(1ZdestRect°dONLNdï    tŸ)8.  By definition, the °dONLNd´Ÿ)edestRect°dONLNd≥    .)8 uses °dONLNdπ    .˙)*integer values for the top-left and bottom°dONLNd„    ˙˛)Ã-°dONLNd‰<"à(>ZDright boundary points.  It is possible to have values too large for °dONLNd(à"ú(>¶the °dONLNd,ú!‘)destRect°dONLNd4‘"˛)8 without°dONLNd=#</x(KZ
  4992. reaching the °dONLNdJ"x.∞)<teLength°dONLNdR#∞/Ã)8 limit.°dONLNdZ<<HR(dZThe °dONLNd^;RG|)nLines°dONLNdd<|H%)*$ field gives the number of lines in °dONLNdà<%Hû)©the edit record, and the °dONLNd°;ûG‰)y
  4993. lineHeight°dONLNd´<‰H˛)F field°dONLNd≤H<T@(pZ:specifies the vertical distance from the ascent line from °dONLNdÏH@T˛(p^*one line of text to the ascent line of the°dONLNdU<a⁄(}Z$next line.  In styled TextEdit, the °dONLNd;T⁄` )û
  4994. lineHeight°dONLNdEU a#)F °dONLNdFU#a˛),may vary for each line depending on the font°dONLNdsb<n(äZ0and font size.  These values are entries in the °dONLNd£amX)÷
  4995. lineHeight°dONLNd≠bXnu)F table.†Ç°ñ 
  4996. öظS
  4997. 0dd°dONLNdˇˇ(æ∞Ijklmop
  4998. °dONLNdˇˇ*0Abcdef†ó°ÿˇˇÄ°÷ˇˇÄ†◊°¥        
  4999. ôÆ˝» ù±ùÖ†µ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†Ÿqù±û∫û±ù±ù∫û∫û±qù√ûÃû√ù√ùÃûÃû√qù’ûfiû’ù’ùfiûfiû’qùÁûûÁùÁùûûÁqù˘ûû˘ù˘ùûû˘qù ûû ù ùûû qùû&ûùù&û&ûqù/û8û/ù/ù8û8û/qùAûJûAùAùJûJûAqùSû\ûSùSù\û\ûSqùeûnûeùeùnûnûeqùwûÄûwùwùÄûÄûw°ÿˇˇÄ†ø†Ÿ†◊°ÿˇˇÄ°÷ˇˇÄ†◊°¥         Õ±ÕɆµ°÷ˇˇÄ†◊†Ÿ°÷ˇˇÄ°ÿˇˇÄ†æ†ŸqÕ±Œ∫Œ±Õ±Õ∫Œ∫Œ±qÕ√ŒÃŒ√Õ√ÕÌÌ√qÕ’ŒfiŒ’Õ’ÕfiŒfiŒ’qÕÁŒŒÁÕÁÕŒŒÁqÕ˘ŒŒ˘Õ˘ÕŒŒ˘qÕ ŒŒ Õ ÕŒŒ qÕŒ&ŒÕÕ&Œ&ŒqÕ/Œ8Œ/Õ/Õ8Œ8Œ/qÕAŒJŒAÕAÕJŒJŒAqÕSŒ\ŒSÕSÕ\Œ\ŒSqÕeŒnŒeÕeÕnŒnŒeqÕwŒÄŒwÕwÕČČw°ÿˇˇÄ†ø†Ÿ†◊"‚Z·o††°§ˇtù~©Ñùũѩũ~ùÅ
  5000. "ùÅ ##˝##˝##Ù#Ñ
  5001. öØö؆£
  5002. ôÆ˝»Ñ
  5003. öØö؆°"‚Z·o††°§ˇt¬~ŒÑŒÅ¬~¬Å¬ÑŒÅ
  5004. "ŒÅ˝Ù######˝ #Ñ
  5005. öØö؆£
  5006. ôÆ˝»Ñ
  5007. öØö؆°"¶Å°ñ 
  5008. Øáª«
  5009. °dONLNdˇˇ(∏à
  5010. LineHeight†ó†É
  5011. IR°dONLNdµÍ‚ˆX(Figure 1–LineHeight°dONLNd…<x(+Z The product °dONLNd’xò)<of the °dONLNd‹òfi) 
  5012. lineHeight°dONLNdÊfi))F (or the largest °dONLNd˜)o)K
  5013. lineHeight°dONLNdo˛)F value in styled TextEdit) and°dONLNd <f(8ZnLines°dONLNd&f¶)*E gives a good approximation, in pixels, of the vertical dimension of °dONLNdk¶∏(8ƒthe °dONLNdo∏)destRect°dONLNdw˛)8 of°dONLNd{<)M(EZthe °dONLNdM(p)TERec°dONLNdÑp)ê)# used. °dONLNdãê)˛) N If this value is greater than 32,768, then unpredictable and erratic behavior°dONLNd⁄)<5q(QZ may result.°dONLNdÊA<Mz* For example:°dONLNdÙZ`f+$'2,400 lines of Chicago 12 point yields °dONLNdYeB)∏nLines°dONLNd!ZBfÇ)*
  5014.  = 2,400 and °dONLNd.YÇe»)@
  5015. lineHeight°dONLNd8Z»fÂ)F = 16.°dONLNdAf`rä(è~nLines°dONLNdGgäsñ)* * °dONLNdJfñr‹)
  5016. lineHeight°dONLNdTg‹s÷)F4 = 2400 * 16 = 38,400.  This is above the 32K limit.°dONLNdäÄ`å(®~%1,200 lines of Times 24 point yields °dONLNdØã8)ÆnLines°dONLNdµÄ8åx)*
  5017.  = 1,200 and °dONLNd¬xãæ)@
  5018. lineHeight°dONLNdÃÄæå€)F = 30.°dONLNd‘å`òä(µ~nLines°dONLNd⁄çäôñ)* * °dONLNd›åñò‹)
  5019. lineHeight°dONLNdÁç‹ô÷)F4 = 1200 * 30 = 36,000.  This is above the 32K limit. ◊X◊
  5020. (ÏZ*TextEdit Record Size Limitations Revisited(Ï1) of 2ˇ°¿Ù%%DSIDICT:_cv
  5021. currentdict /bu known {bu}if
  5022. userdict /_cv known not{userdict /_cv 30 dict put}if
  5023. _cv begin
  5024. /bdf{bind def}bind def
  5025. currentscreen/cs exch def/ca exch def/cf exch def
  5026. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5027. /ss{//cf //ca //cs setscreen}bdf
  5028. /stg{ss setgray}bdf
  5029. /strgb{ss setrgbcolor}bdf
  5030. /stcmyk{ss cvcmyk}bdf
  5031. /min1{dup 0 eq{pop 1}if}bdf
  5032. end
  5033. currentdict /bn known {bn}if
  5034. †øÍ◊#ˇ ˇˇˇˇ#◊ 
  5035. IR,Times
  5036. .+6-Macintosh Technical Notes /4/˘
  5037. °dONLNd)F*;In both of the examples above, the number of characters in °dONLNd;F)⁄(Edthe edit record was less than°dONLNdY)5>(Q632,768.
  5038. °dONLNdaM\™*'Check All Constraints
  5039. °dONLNdwiu4*Both ,
  5040. Courier°dONLNd|h4tl)TELength°dONLNdÑilu”)8 and the size of the °dONLNdôh”t )gdestRect°dONLNd°i u\)8 must be under °dONLNd∞i\u⁄)Qthe 32K limit.  You can°dONLNd»vÇQ(û6 compute an °dONLNd”vQLj)9#approximate vertical height of the °dONLNdˆuˆÅ.)•destRect°dONLNd˛v.Ç∞)8 by finding the product of °dONLNdu∞Å⁄)ÇnLines°dONLNd Éè,(´6and °dONLNd$Ç,ér)
  5041. lineHeight°dONLNd.Érèπ)F (or the largest °dONLNd?Çπéˇ)G
  5042. lineHeight°dONLNdIɡèy)F value in styled TextEdit).°dONLNde≥øÇ(€6Further Reference: fi4fi˘°dONLNdx¿*Ã.+
  5043. •°dONLNdz¿<Ãç)Inside Macintosh°dONLNdä¿çÃ7)Q!, Volumes I-371 & V-259, TextEdit°dONLNd¨Ã*ÿ.(ÙH•°dONLNdÆÃ<ÿ•)M.OV.ManagerAbuse ◊4◊˘
  5044. (Ï62) of 2(ÏJ*TextEdit Record Size Limitations RevisitedˇR◊#ˇ ˇˇˇˇ#◊†Ç 
  5045. /ZÅ#
  5046.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5047. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5048. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5049. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5050. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5051.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5052. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  5053. IR.°dONLNdn<ź(õZ
  5054. TextEdit Q&As
  5055. °dONLNdÄ<èZ*Text°dONLNdÄkè˛(´âM.TX.TextEdit.Q&As
  5056. °dONLNd'õ<ßt(√Z Revised by:°dONLNd3õÑߡ)HDeveloper Support Center°dONLNdLõ¥ß˛(√“
  5057. December 1992°dONLNdZß<≥q(œZ Written by:°dONLNdfßÑ≥ˇ)HDeveloper Support Center°dONLNdßæ≥˛(œ‹ October 1990°dONLNdåø<À⁄(ÁZThis Technical Note contains a °dONLNd´ø⁄À˛)û9collection of Q&As relating to a specific topic—questions°dONLNdÂÀ<◊†(ÛZGyou’ve sent the Developer Support Center (DSC) along with answers from °dONLNd,À†◊˛(Ûæthe DSC engineers.°dONLNd?◊<„u(ˇZ
  5058. While DSC °dONLNdI◊u„˛)9Lengineers have checked the Q&A content for accuracy, the Q&A Technical Notes°dONLNdñ„<Ôq( Z don’t have °dONLNd°„qÔ˛)5Qthe editing and organization of other Technical Notes. The Q&A function is to get°dONLNdÛÔ<˚Ÿ(Znew technical information and °dONLNdÔŸ˚˛)ù6updates to you quickly, saving the polish for when the°dONLNdH˚<(#Z,information migrates into reference manuals.°dONLNdu<k*:Q&As are now included with Technical Notes to make access °dONLNdØk˛(;âto technical updates easier for°dONLNdœ<+.(GZ/you. If you have comments or suggestions about °dONLNd˛.+˛)Ú*Q&A content or distribution, please let us°dONLNd)+<7\(SZknow °dONLNd.+\7˛) Iby sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical°dONLNdx7<Ci(_Z9questions about Q&A content to DEVSUPPORT for resolution.°dONLNd≤O<[¨*New Q&As this month:°dONLNd«[<g* #Extending TextEdit beyond 32K limit°dONLNdÎg<s** *Controlling TEIdle’s insertion point color ûXû
  5059. °dONLNdò<ß7*4#Extending TextEdit beyond 32K limit
  5060. °dONLNd:ß<≥x*
  5061. Date written:°dONLNdHßà≥¨)L9/16/92°dONLNdP≥<øÅ(€ZLast reviewed:°dONLNd_≥àø¨)L11/1/92°dONLNdgÀ<◊‰(ÛZVHow do I get around the 32K limit in TextEdit? For example, if I have a 64K text file °dONLNdΩÀ‰◊˛(Ûand I°dONLNd√◊<„Ç(ˇZIwant to read it in and display it in a window, I can only read the first °dONLNd ◊Ç„˛(ˇ†32K. How do I make the°dONLNd#„<Ôx( ZDtext display smoothly when I need to read the next block of text in?°dONLNdhÔ<˚N* ___°dONLNdl<º*JUnfortunately, there’s no supported way of doing this. In the early days, °dONLNd∂º˛(/⁄ TextEdit was°dONLNd√<”(;Z designed for use primarily with °dONLNd„”˛)ó<the Dialog Manager, for displaying and editing small amounts°dONLNd <+/(GZ4of text at a time. Since then, many developers have °dONLNdT/+˛)Û*used it, or wanted to use it for much more°dONLNd+<7Ã(SZthan it was intended. See the °dONLNdù+Ã7˛)ê;Technical Note “Don’t Abuse the Managers,” available on the°dONLNdŸ7<Cπ(_ZDeveloper’s CD, (path: °dONLNd7πC˛)};“Dev.CD Sept 92:Technical Documentation:Macintosh Technical°dONLNd,C<OÓ(kZ"Notes:Overview:Managerial Abuse”).°dONLNdO[<g¬*The Word Solution Engine °dONLNdh[¬g˛)Ü>by DataPak is a replacement for TextEdit that allows you to go°dONLNdßg<s«(èZSbeyond the 32K limit, as well as including many other features. Other packages are °dONLNd˙g«s˛(è available as°dONLNds<≤(õZwell. Check the Redgate °dONLNds≤–)v9Macintosh Directory on AppleLink or publications such as °dONLNdXs–˛(õÓMacTutor°dONLNda<ã®(ßZmagazine to find them. ◊X◊
  5062. *E
  5063. TextEdit Q&As(Ï1) of 6ˇ°¿Ù%%DSIDICT:_cv
  5064. currentdict /bu known {bu}if
  5065. userdict /_cv known not{userdict /_cv 30 dict put}if
  5066. _cv begin
  5067. /bdf{bind def}bind def
  5068. currentscreen/cs exch def/ca exch def/cf exch def
  5069. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5070. /ss{//cf //ca //cs setscreen}bdf
  5071. /stg{ss setgray}bdf
  5072. /strgb{ss setrgbcolor}bdf
  5073. /stcmyk{ss cvcmyk}bdf
  5074. /min1{dup 0 eq{pop 1}if}bdf
  5075. end
  5076. currentdict /bn known {bn}if
  5077. †øp◊#ˇ ˇˇˇˇ#◊ 
  5078. IR,Times
  5079. .+6-Macintosh Technical Notes /4/˘
  5080. °dONLNd,2**Controlling TEIdle’s insertion point color
  5081. °dONLNd+,8T*
  5082. Date written:°dONLNd9,d8Ç)L7/6/92°dONLNd@8D](`6Last reviewed:°dONLNdO8dDà)L11/1/92°dONLNdWP\Ç(x6QIs it possible to control the color of the insertion point when I use TEIdle? If °dONLNd®PÇ\⁄(x†I have a light blue°dONLNdº\hÜ(Ñ6background color, the °dONLNd“\Üh⁄)nDcaret is always the invert of that background color and doesn’t have°dONLNdhté(ê6Senough contrast to see it. I want to make the color of the caret black if possible.°dONLNdktÄ** ___°dONLNdoåò©*VAs is often the case, some of the seemingly simplest questions tend to yield the most °dONLNd≈å©ò⁄(¥« interesting°dONLNd—ò§(¿60answers. Succinctly, your question stabs at the °dONLNdò§⁄)Ë(wobbly knees of QuickDraw’s color model.°dONLNd*§∞π(Ã6 Sample code to change the color °dONLNdJ§π∞⁄)°<of the caret in a TextEdit record is in the Snippets folder.°dONLNdá∞ºŸ(ÿ6(Here’s how to implement the color caret.°dONLNd∞»‘1*;You can use the caretHook field of the TextEdit record (IM °dONLNdλ1‘⁄(O$I-379). Basically, this procedure is°dONLNd‘‡/(¸6<called repeatedly by TEIdle to draw the caret. The function °dONLNdL‘/‡⁄(¸M$calls InvertRect each time. It draws°dONLNdq‡Ïq(6the caret, and then °dONLNdÖ‡qÏ⁄)YLit erases the caret. Unfortunately, this function needs to be implemented in°dONLNd“ϯ (6%assembly. So there are a few gotchas:°dONLNd¯ø*^• The pointer to the rectangle for the caret is passed on the stack (not the whole rectangle).°dONLNdW1* 9• The function InvertRect becomes _InverRect in assembly.°dONLNdë(* 1• You can only use A4 for scratch (A0 and A1 are °dONLNd¬(⁄)Ì*blown away by PaintRect), and then only if°dONLNdÌ(4å(P6you saved and restore it.°dONLNd4@M* C• Make sure you pop off the rectangle pointer if you do not use it.°dONLNdKLXû*The default system function °dONLNdgLûX⁄)ÜBis simply _InverRect because the rectangle pointer is on the stack°dONLNd™Xd (Ä61and _InverRect pops it off. For color, inverting °dONLNd€X d⁄)Û(is not the best idea, as you have noted.°dONLNddpX(å6Inversion, if °dONLNddXp⁄)@Lit isn’t black and white, does not give you the most contrast. Thus, we need°dONLNd_p|U(ò6
  5083. another idea.°dONLNdmàî¶*JBut, remember, we have a requirement to paint once, and then erase on the °dONLNd∑à¶î⁄(∞ƒ
  5084. next pass.°dONLNd¬î†«(º6$Inversion works nicely this way. To °dONLNdÊ⁄)Ø6meet this requirement, use Xor mode with PaintRect. As°dONLNd†¨
  5085. (»60you know, Xor mode is “or” mode with the double °dONLNdM†
  5086. ¨⁄)ı-1s being set to 0 instead of 1. This trait is°dONLNd{¨∏ñ(‘6Oideal in your situation because, always having the same caret pattern, drawing °dONLNd ¨ñ∏⁄(‘¥
  5087. a second time°dONLNdÿ∏ƒÃ(‡6]obliterates the previous drawing of the caret. Thus, we get the blinking behavior. And, with °dONLNd5∏Ã⁄(‡Íthe°dONLNd9ƒ–k(Ï6Macintosh II and °dONLNdJƒk–⁄)SJColor QuickDraw, we get these cool things called pixel patterns (IM V-55).°dONLNdï–‹√(¯6#You can use your own pixel pattern °dONLNd∏–√‹⁄)´;as the pen pattern, bring it in from the resource, and then°dONLNdÙ‹Ë}(6Luse PaintRect in the patXor mode to achieve the desired effect. Done, right?°dONLNd    BÙπ*"Unfortunately, here we run into a °dONLNd    dÙπ⁄)°9major flaw of QuickDraw: It is based on two color models,°dONLNd    û @((6indexed °dONLNd    ¶@ ⁄)(Uand direct. And, arithmetic operations are performed on the pixel values, and not the°dONLNd    ¸ µ(46Vcolors. In the indexed model, a pixel value of 0x00 is white. (The pixel value in the °dONLNd
  5088. R µ⁄(4”indexed°dONLNd
  5089. Z$
  5090. (@67color model is really an index into a color table.) If °dONLNd
  5091. ë
  5092. $⁄)Ú)you Xor it with 0xFF, you’ll get 0xFF, or°dONLNd
  5093. ª$0£(L6black. If you Xor 0xFF with °dONLNd
  5094. ◊$£0⁄)ã?0xFF, you’ll get 0x00 or white again. On the other hand (in the°dONLNd 0<√(X6&direct color model), a pixel value of °dONLNd =0√<⁄)´80x00 is black. If you Xor it with 0xFF, you’ll get 0xFF,°dONLNd v<Hú(d6or white. This is a problem.°dONLNd ìT`Ö*OSo, you’ll need to perform conditional caret coloring (sounds like a disease). °dONLNd ‚TÖ`⁄(|£Depending on the°dONLNd Û`l(à65depth, you’ll need to use a different pixel pattern. °dONLNd (`lΩ)Ï#One good way is to use DeviceLoop (°dONLNd K`Ωl⁄)πInside°dONLNd RlxI(î6    Macintosh°dONLNd [lIx§)1G Volume VI, page 21-23). Though it’s included with System 7.0, there’s °dONLNd ¢l§x⁄(î¬ a simulated°dONLNd ÆxÑ.(†6one °dONLNd ≤x.Ñô)Fas described in the article “Multiple Screens Revealed” on page 57 of °dONLNd ¯xôÑæ(†∑develop°dONLNd ˇxæÑ⁄)% #10.°dONLNd
  5095. ÑêK(¨6>DeviceLoop lets you provide a routine that is called for each °dONLNd
  5096. CÑKê⁄(¨iscreen that the drawing area°dONLNd
  5097. `êú(∏63touches. In this case, the drawing routine is your °dONLNd
  5098. ìêú⁄)Í-PaintRect routine for the caret. This drawing°dONLNd
  5099. ¡ú®≠(ƒ6Wroutine gets passed the depth of the screen. So, based on the depth of the screen, you °dONLNdú≠®⁄(ƒÀ    can use a ◊4◊˘
  5100. (Ï62) of 6(Ïπ
  5101. TextEdit Q&Asˇå◊#ˇ ˇˇˇˇ#◊ 
  5102. IR,Times
  5103. .+Z-Developer Support Center(-fi
  5104. December 1992 /X/
  5105. °dONLNdˇˇ(EZVdifferent pixel pattern to draw with. For pixel depth of 32 or direct color mode, you °dONLNdˇˇ(E˜can use°dONLNdˇˇ(QZ>one pattern, and for the rest you can use a different pattern.°dONLNdˇˇ*ENote, the drawing routine used by DeviceLoop allows you to pass in a °dONLNdˇˇ(i™LONGINT of userdata.°dONLNdˇˇ(uZZWith this longint, you can pass in the pointer to the rectangle from the assembly routine.
  5106. °dONLNdˇˇ*'+Resizing a Macintosh edit field for TEPaste
  5107. °dONLNdˇˇ* Written:°dONLNdˇˇ)L11/27/91°dONLNdˇˇ(¥ZLast reviewed:°dONLNdˇˇ)L11/27/91°dONLNdˇˇ(ÃZ    I have a °dONLNdˇˇ)(Vsmall edit field and when I call TEPaste, the edit field contents scroll up. How can I°dONLNdˇˇ(ÿZMcalculate what the height of the edit field would be after the paste, resize °dONLNdˇˇ(ÿØthe edit field to be that°dONLNdˇˇ(‰Zsize, and then do the paste?°dONLNdˇˇ* ___°dONLNdˇˇ*-There are a couple of ways to implement this:°dONLNdˇˇ*
  5108. Method #1:°dONLNdˇˇ* N1. Set the clip region to something other than the viewRect of the edit field.°dONLNdˇˇ* <2. Call TEPaste or TEStylPaste to insert the clipboard text.°dONLNdˇˇ* 63. Call TEGetHeight to get the new height of the text.°dONLNdˇˇ* C4. Set the viewRect of the TERec to the new height. Call TECalText °dONLNdˇˇ(P´for good measure (and°dONLNdˇˇ(\Zgood lineStarts).°dONLNdˇˇ* A5. Finally, set the clip region back to normal and call TEUpdate.°dONLNdˇˇ*
  5109. Method #2:°dONLNdˇˇ* V1. Call TENew or TEStylNew to allocate a brand spankin’ new temporary TERec, and give °dONLNdˇˇ(å
  5110. it a°dONLNdˇˇ(òZ^viewRect and destRect that’s off the screen but that has the same width as the original TERec.°dONLNdˇˇ*     2. Next, °dONLNdˇˇ)+Qcopy the hText handle of the window’s TERec into the hText field of the temporary°dONLNdˇˇ(∞Z*TERec (good job for BlockMove [IM II-44]).°dONLNdˇˇ* Y3. Call TECalText and TEActivate on it; then paste the clipboard text into the temporary °dONLNdˇˇ(º¯TERec.°dONLNdˇˇ(»ZXSince the view and dest Rects are off the screen, none of this will be seen by the user.°dONLNdˇˇ* [4. Call TEGetHeight to get the new height, then copy the text back into the original TERec.°dONLNdˇˇ* O5. Finally, call TECalText, then TEUpdate and TEActivate on the original TERec.°dONLNdˇˇ* Method #1 has less overhead and °dONLNdˇˇ)¶9is a little easier to implement. However, if you have any°dONLNdˇˇ(Zcustom hooks installed in °dONLNdˇˇ){@your TERec, then you probably want to let TextEdit do as much of°dONLNdˇˇ(Z>the work as possible. In this case, method #2 is a better way.
  5111. °dONLNdˇˇ*'6Saving and restoring styled Macintosh TextEdit records
  5112. °dONLNdˇˇ* Written:°dONLNdˇˇ)L11/26/90°dONLNdˇˇ(OZLast reviewed:°dONLNdˇˇ)L12/19/90°dONLNdˇˇ(gZ,How do I save and restore Macintosh records °dONLNdˇˇ)⁄0created with TextEdit that contain styles? Where°dONLNdˇˇ(sZ1can I find additional information or sample code?°dONLNdˇˇ* ___°dONLNdˇˇ*;There’s no standard for saving text with styles created by °dONLNdˇˇ(óu"TextEdit, so all we can offer is a°dONLNdˇˇ(£ZQrecommendation that’s modeled after the way that TECopy works on styled text. In °dONLNdˇˇ(£styled°dONLNdˇˇ(ØZ_TextEdit, the style information is stored separately from the text rather than embedded within °dONLNdˇˇ(Øit.°dONLNdˇˇ(ªZSTECopy maintains this separation when styled text is copied, so our recommendation °dONLNdˇˇ(ªÔ    maintains°dONLNdˇˇ(«Zthis separation, too. ◊X◊
  5113. *%
  5114. TextEdit Q&As(Ï3) of 6ˇ◊#ˇ ˇˇˇˇ#◊ 
  5115. IR,Times
  5116. .+6-Macintosh Technical Notes /4/˘
  5117. °dONLNd)5Û*$0To save the text part, you could make a file of °dONLNd0)Û5⁄)€/type TEXT and save the text in the data fork of°dONLNd`5Aî(]6Qthe file, like TeachText does. You could also save it in a resource of type TEXT.°dONLNd≤MYè*The best way to save the °dONLNdÀMèY⁄)wDstyle information is to use the StScrpRec record. Other records used°dONLNdYe.(Å6=by styled TextEdit contain references to other structures or °dONLNdMY.e⁄(ÅL%they contain only a part of the style°dONLNdseqü(ç6information, and that makes °dONLNdèeüq⁄)á=saving them awkward. The StScrpRec doesn’t contain references°dONLNdÕq}_(ô6Gto any other structures, and it contains enough information to rebuild °dONLNdq_}⁄(ô}the entire tree of TextEdit°dONLNd0}âº(•6Xstructures. When you call TECopy on styled text, both a 'TEXT' and 'styl' scrap type is °dONLNdà}ºâ⁄(•⁄placed°dONLNdèâïl(±6Ainto the desk scrap. The 'TEXT' type just contains the text. The °dONLNd–âlï⁄(±ä'styl' type contains a°dONLNdÁï°(Ω66StScrpRec containing all of the style information for °dONLNdï°⁄)˘*the copied text. TextEdit doesn’t maintain°dONLNdH°≠¯(…6/a StScrpRec for the entire text buffer, so you °dONLNdw°¯≠⁄)‡-have to tell TextEdit to do this for you when°dONLNd•≠π‡(’6+you’re ready to save the style information.°dONLNd—≈—¬*#Fortunately, one call does it all. °dONLNdÙ≈¬—)™Inside Macintosh°dONLNd≈—u)T Volume V, page °dONLNd≈u—⁄)_268, documents the°dONLNd'—›H(˘6@GetStylScrap routine. It creates a new StScrpRec record, places °dONLNdg—H›⁄(˘f all the style information of the°dONLNdà›Èµ(6Zselected text into it, and returns a handle to this StScrpRec. First, select the text you °dONLNd‚›µÈ⁄(”want to°dONLNdÍÈıê(6Psave either by calling TESetSelect or by setting the selStart and selEnd fields °dONLNd:Èêı⁄(Æof the TextEdit°dONLNdJır(6Jrecord if you don’t want the selection to be visible to the user. (If you °dONLNdîır⁄(êdo this, remember to°dONLNd©
  5118. d()6restore the old °dONLNdπd
  5119. ⁄)LIvalues of selStart and selEnd after you get the StScrpHandle.) Next, call°dONLNd
  5120. fi(56)GetStylScrap to construct the StScrpRec. °dONLNd,
  5121. fi⁄)Δ1You can now save the resulting StScrpRec, perhaps°dONLNd^%*(A6<in a resource of type 'styl' or in whatever way you see fit.°dONLNdõ1=∏*!Reading the text and styles back °dONLNdº1∏=⁄)†:into a TextEdit record isn’t much more complicated. First,°dONLNd˜=Ix(e6Jread the text back into a buffer and read the 'styl' resource (or however °dONLNdA=xI⁄(eñyou saved it) into a°dONLNdVIU)(q6:StScrpRec. Create a styled TextEdit record (or use an old °dONLNdêI)U⁄(qG%one), then call TEStylInsert, passing°dONLNd∂Uaû(}6 it a pointer to the text buffer °dONLNd÷Uûa⁄)Ü?and a handle to the StScrpRec. Your TextEdit record should then°dONLNdam(â6:contain and display your original styled text. That’s all!
  5122. °dONLNdRyà´*Macintosh SetClikLoop procedure and TERec clikLoop field
  5123. °dONLNdãàî>* Written:°dONLNdîàdîà)L7/30/91°dONLNdúî†](º6Last reviewed:°dONLNd´îd†Ç)L8/1/91°dONLNd≤¨∏:(‘68I have had some problems with the SetClikLoop procedure °dONLNdͨ:∏⁄(‘X that don’t appear when I set the°dONLNd     ∏ƒ_(‡6clikLoop field °dONLNd    ∏_ƒ⁄)GKdirectly (in C). Why does TextEdit’s SetClikLoop procedure create a special°dONLNd    fƒ–N(Ï6Cprocedure to call my clikLoop routine, rather that just installing °dONLNd    ©ƒN–Ω(Ïlthe clikLoop directly? °dONLNd    ¿ƒΩ–⁄)oInside°dONLNd    «–‹I(¯6    Macintosh°dONLNd    ––I‹ú)1H says you can set the clikLoop field directly in assembly. Why not in C?°dONLNd
  5124. ‹Ë*(6___°dONLNd
  5125. ÙÃ*`The short answer is that the special procedure is a glue routine for shuttling a result between °dONLNd
  5126. }ÙÃ⁄(Íthe°dONLNd
  5127. Å º((6Xstack and the register D0. The larger question is why does installing clikLoop directly °dONLNd
  5128. Ÿº ⁄((⁄work?°dONLNd
  5129. fl ã(46C, I think, is the culprit.°dONLNd
  5130. ˚$0Ã*ZBut, before I get ahead of myself, let me explain the SetClikLoop procedure. As you know, °dONLNd U$Ã0⁄(LÍthe°dONLNd Y0<û(X6Tclick loop routine has no parameters but it does return a Boolean result (IM I-380).,
  5131. Courier
  5132.     °dONLNd ÆHS!*5FUNCTION MyClikLoop : Boolean; { Pascal declaration }°dONLNd ‰R]*
  5133. 0pascal Boolean MyClikLoop();   { C declaration }
  5134. °dONLNd ht¥*Now, MyClikLoop is called by °dONLNd 2h¥t⁄)ú9the TextEdit Manager from inside the TEClick routine. The°dONLNd ltÄÆ(ú6Qway the code was written, TEClick expects to get the Boolean result from D0. For °dONLNd ΩtÆÄ⁄(úÃassembly°dONLNd ΔÄåN(®6@programmers, this is no problem. In Pascal, the return value is °dONLNd
  5135. ÄNå⁄(®lplaced on the stack. So, D0°dONLNd
  5136. "åòæ(¥6Rdoes not contain your routines’ Boolean and what TEClick grabs will be “who knows °dONLNd
  5137. tåæò⁄(¥‹what”°dONLNd
  5138. zò§.(¿6:and your program should crash. SetClikLoop will install a °dONLNd
  5139. ¥ò.§⁄(¿L#glue routine that calls MyClikLoop. ◊4◊˘
  5140. (Ï64) of 6(Ïπ
  5141. TextEdit Q&Asˇ*◊#ˇ ˇˇˇˇ#◊ 
  5142. IR,Times
  5143. .+Z-Developer Support Center(-fi
  5144. December 1992 /X/
  5145. °dONLNd<)<(EZ5The glue routine will move the result from the stack °dONLNd5<)˛(EZ&to D0. By the way, this information is°dONLNd\)<55(QZ-documented on pages 237–238 of Volume Two of °dONLNdâ)55ö)˘Macintosh Revealed,°dONLNdú)ö5˛)e Second Edition, by°dONLNd∞5<Aú(]ZStephen Chernicoff.°dONLNdƒM<Yó*Now why is your °dONLNd‘MóY˛)[Aprogram causing problems when you use SetClikLoop? You might have°dONLNdY<eŒ(ÅZPdeclared your MyClikLoop as a C function. Since MyClikLoop takes no parameters, °dONLNdfYŒe˛(ÅÏ
  5146. nothing is°dONLNdqe<q≥(çZRput on the stack. But C, unlike Pascal, places its return value in D0. So, for C, °dONLNd√e≥q˛(ç—the glue routine°dONLNd‘q<}≠(ôZNis not needed. On the other hand, if you use the SetClikLoop routine with a C °dONLNd"q≠}˛(ôÀroutine, you will°dONLNd4}<â(•Z/take the top 2 bytes off the stack and clobber °dONLNdc}â˛)’-D0 with the wrong answer. Thus, you might get°dONLNdëâ<ïl(±Z    problems.°dONLNdõ°<≠C*8Though the C routine may work by setting it directly to °dONLNd”°C≠˛(…a(the clikLoop field, doing it that way is°dONLNd¸≠<π2(’Z2not the supported method. You should declare your °dONLNd.≠2π˛)ˆ(MyClikLoop function as a Pascal function°dONLNdWπ<≈£(·Zand use SetClikLoop.
  5147. °dONLNdl›<Ïfl*'=Special handling for Control-P keyboard input in a Mac dialog
  5148. °dONLNd™Ï<¯b* Written:°dONLNd≥Ï௶)L6/5/91°dONLNd∫¯<Å( ZLast reviewed:°dONLNd…¯à¶)L8/1/91°dONLNd–<{(8Z@Under System 6, when Control-P is pressed, a DLE character (hex °dONLNd{˛(8ô10) appears in a Macintosh°dONLNd+<(s(DZ<dialog’s editText field. Under System 7, pressing Control-P °dONLNdgs(˛(Dëproduces no change in the°dONLNdÅ(<4Ω(PZGeditText box. The character is fed in via a normal (unaltered) keyDown °dONLNd»(Ω4˛(P€ event fed to°dONLNd’4<@Í(\ZWDialogSelect. Does Control-P have some special meaning to DialogSelect or TextEdit now?°dONLNd-@<LN* ___°dONLNd1X<dÙ**Believe it or not, and it took several of °dONLNd[XÙd˛)∏9us scratching our heads to figure this out; yes, it does,°dONLNdïd<p¿(åZand this is by design! What °dONLNd±d¿p˛)Ñ?you are running into is the Dialog Manager and TextEdit working°dONLNdÒp<|s(òZ together to °dONLNd˝ps|˛)7Imake Cut, Copy, and Paste function keys work on an extended keyboard. The°dONLNdG|<àé(§ZEfunction keys on the top of an extended keyboard return $10 as their °dONLNdå|éà˛(§¨ASCII keycode. Thus,°dONLNd°à<îs(∞ZCwhen TEKey detects that it is being called from dialog select, and °dONLNd‰àsî˛(∞ëthe key you pass is a $10, it°dONLNdî<†Æ(ºZthen looks for the event °dONLNdîÆ†˛)rDrecord on the stack and gets the raw keycode to determine which edit°dONLNd`†<¨·(»Z_operation to perform. The bottom line is that it will not then enter the $10 in the edit field.°dONLNd¿∏<ƒì*There is a simple °dONLNd“∏ìƒ˛)WLworkaround, and that is to install a filter proc in your dialog that detects°dONLNdƒ<–(ÏZ*keystrokes (actually it could always just °dONLNdIƒ–˛)≈3look for this certain keystroke) and passes them to°dONLNd}–<‹
  5149. (¯Z,TEKey itself, thus skirting the whole issue.
  5150. °dONLNd™Ù<ê*'1Dimming and disabling a specific TEditText object
  5151. °dONLNd‹<b* Written:°dONLNdÂà¶)L8/8/91°dONLNdÏ<Å(7ZLast reviewed:°dONLNd˚à¨)L8/13/91°dONLNd    '<3j(OZHow can °dONLNd     'j3˛).SI dim and disable a specific TEditText object in my TDialogView so the field is not°dONLNd    _3<?e([Z    editable?°dONLNd    j?<KN* ___°dONLNd    nW<cà*The trick is to °dONLNd    ~Wàc˛)LDuse the TView methods Dimstate and ViewEnable to disable and dim the°dONLNd    √c<oÆ(ãZJTEditText Views, and then do a TEditText.StopEdit (which disables editing °dONLNd
  5152.  
  5153. cÆo˛(ãÃin the TEditText°dONLNd
  5154. o<{
  5155. (óZ+box), and in the other case enable dimming °dONLNd
  5156. Io
  5157. {˛)Œ3and the view itself and use the TEditText.StartEdit°dONLNd
  5158. }{<á≈(£ZP(which enables editing in the TEditText box), as shown in the C++ example below:,
  5159. Courier
  5160.     °dONLNd
  5161. Œì<ûö*F            anEditText2->DimState(TRUE,kDontRedraw);        // disable°dONLNd ù<®;*
  5162. 3            anEditText2->ViewEnable(FALSE,kRedraw); ◊X◊
  5163. *(
  5164. TextEdit Q&As(Ï5) of 6ˇÍ◊#ˇ ˇˇˇˇ#◊ 
  5165. IR,Times
  5166. .+6-Macintosh Technical Notes /4/˘,
  5167. Courier
  5168.     °dONLNd(Ã*$            anEditText2->StopEdit();°dONLNd11<v*F            anEditText1->DimState(FALSE,kDontRedraw);        // enable°dONLNdx;F*
  5169. 2            anEditText1->ViewEnable(TRUE,kRedraw);°dONLNd´EP
  5170. *
  5171. 1            anEditText1->StartEdit(TRUE,fTEView);
  5172. °dONLNd›[gï*NMacApp sample code using this technique is included with DTS’s Snippets files.
  5173. °dONLNd,éO*'*Get TEHandle from DialogPeek, not GetDItem
  5174. °dONLNdWéö>* Written:°dONLNd`édöà)L1/17/92°dONLNdhö¶](¬6Last reviewed:°dONLNdwöd¶à)L2/17/92°dONLNd≤æE(⁄6
  5175. I want to °dONLNdâ≤Eæ⁄)-Rshow all characters in my Macintosh control panel as bullets where the password is°dONLNd‹æ ı(Ê6+typed in. I cannot get the TECustomHook to °dONLNdæı ⁄)›.work properly, it crashes before it gets to my°dONLNd6 ÷(Ú65hook routine. In the following Think C example, CPtr °dONLNdk ÷⁄(Ú9'is dereferenced from the handle used in°dONLNdì÷‚æ(˛6$the control panel’s cdevValue field:
  5176.     °dONLNd∏Ó˘l*D   GetDItem(DPtr, ADMINPWTE+NumItems, &theType, &theItem, &theRect);°dONLNd˝¯÷*
  5177. &   CPtr->myTEProc = (ProcPtr)TEPWHook;°dONLNd$
  5178. +*
  5179. 7   TECustomHook(intDrawHook, &CPtr->myTEProc, theItem);
  5180. °dONLNd\ ** ___°dONLNd`$0„*(GetDItem does NOT return a TEHandle; it °dONLNdà$„0⁄)À6returns a handle to the current text of the edit item.°dONLNdø0<Q(X6    You must °dONLNd»0Q<⁄)9Cget TEHandle from DialogPeek and must always monitor and change the°dONLNd <Hq(d6ETECustomHook on the fly. There is only one TEHandle for a dialog, no °dONLNdQ<qH⁄(dèmatter how many edit°dONLNdfHT∞(p6Xitems are associated with the dialog. See the description of the DialogRecord data type °dONLNdæH∞TΩ(pŒin °dONLNd¡HΩT⁄)
  5181. Inside°dONLNd»T`M(|6
  5182. Macintosh.
  5183. °dONLNd”xáP*'-Cursor flicker while using Macintosh TextEdit
  5184. °dONLNdáì>* Written:°dONLNd    ádìÇ)L5/6/92°dONLNdìü](ª6Last reviewed:°dONLNdìdüà)L9/15/92°dONLNd'´∑fl(”6*The cursor flashes when the user types in °dONLNdQ´fl∑⁄)«4TextEdit fields in my Macintosh application. This is°dONLNdÜ∑√U(fl6Bdone in TEKey. I notice that most programs hide the cursor once a °dONLNd»∑U√⁄(flskey is pressed. I don’t care°dONLNdÂ√œ÷(Î6)for this because then I have to move the °dONLNd√÷œ⁄)æ7mouse to see where I am. Is this a typical fix for this°dONLNdFœ€∏(˜6!problem and an accepted practice?°dONLNdh€Á** ___°dONLNdlÛˇŒ*(There’s very little you can do to avoid °dONLNdîÛŒˇ⁄)∂6this. The problem is that every time you draw anything°dONLNdÀˇ ('6to the screen, if the °dONLNd·ˇ ⁄)gEcursor’s position intersects the rectangle of the drawing being done,°dONLNd' H(36?QuickDraw hides the cursor while it does the drawing, and then °dONLNdf H⁄(3fshows it again to keep it from°dONLNdÖ#ç(?6Maffecting the image being drawn beneath it. Every time you enter a character °dONLNd“ç#⁄(?´in TextEdit, the°dONLNd„#/Œ(K6]nearby characters are redrawn. Usually this is invisible because the characters just line up °dONLNd@#Œ/⁄(KÏon°dONLNdC/;≠(W6]top of their old images, but if the cursor is nearby and visible, it will flicker while it’s °dONLNd†/≠;⁄(WÀ    hidden to°dONLNd™;G4(c6draw °dONLNdØ;4G⁄)Tthe text. This is why virtually all programs call ObscureCursor when the user types.°dONLNd    GSfi(o6)Also, most users don’t want the image of °dONLNd    -GfiS⁄)Δ5the cursor obscuring text they might be referring to,°dONLNd    cS_S({6Byet they don’t want to have to move it away and then move it back °dONLNd    •SS_⁄({qto make selections. Because°dONLNd    ¡_k8(á6it’s so °dONLNd    …_8k⁄) Tcommonplace, hiding the cursor probably won’t bother your users; in fact, they might°dONLNd
  5185. kw5(ì6<very well prefer the cursor hidden. This, combined with the °dONLNd
  5186. Zk5w⁄(ìS%fact that there’s very little you can°dONLNd
  5187. ÄwÉ√(ü6\do to help the flickering, suggests that you should obscure the cursor while the user types. ◊4◊˘
  5188. *M6) of 6(Ïπ
  5189. TextEdit Q&Asˇ2◊#ˇ ˇˇˇˇ#◊†Ç 
  5190. /_Å(
  5191.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5192. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5193. .R…R…+bBNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5194. ({öDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  f!f_°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5195. 0(UÙ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5196.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5197. (Za    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  5198. d.°dONLNdn<Ÿ(õZTextEdit Technicalities
  5199. °dONLNdÄ<èZ*Text°dONLNdÄyè˛(´óM.TE.TextEditTech
  5200. °dONLNd0õ<ßt(√Z Revised by:°dONLNd<õÑßΩ)H
  5201. Mary Burke°dONLNdGõÀ߲(√È
  5202. April 1990°dONLNdRß<≥q(œZ Written by:°dONLNd^ßÑ≥Ω)H
  5203. Mary Burke°dONLNdiß∏≥˛(œ÷
  5204. February 1990°dONLNdwø<À‘(ÁZNThis Technical Note discusses some areas in TextEdit that have not previously °dONLNd≈ø‘À(ÁÚ been clearly°dONLNd“À<◊y(ÛZ documented.°dONLNdfi◊<„Ó* Changes since February 1990:°dONLNd˙◊Ó„ú)≤!  Added a note about the changes °dONLNd◊ú„)Æin TextEdit for System°dONLNd2‰<‹( ZSoftware 6.0.5, documented the °dONLNdQ‰‹@)†low-memory global ,
  5205. Courier°dONLNdc„@Ôè)d TESysJust, °dONLNdn‰è)Oclarified information about°dONLNdäÒ<˝ñ(Ztext direction and °dONLNdùñ¸‹)Z
  5206. _TESetJust°dONLNdßÒ‹˝v)F, discussed problems with the °dONLNd≈v¸ )ö SetWordBreak°dONLNd—Ò ˝œ)T °dONLNd“Òœ˝)
  5207. routine along°dONLNd‡˝<    Ó(%Z^with a solution to work around it, and described the differences in dialog text item behavior. 4X4/
  5208. °dONLNd?.<=Ø*4TextEdit in 6.0.5
  5209. °dONLNdQI<Uô*MIn addition to all the features of earlier versions, TextEdit 3.0 now allows °dONLNdûIôU(q∑you to take advantage of°dONLNd∑U<a"(}Z.the Script Manager’s handling of systems with °dONLNdÂU"a)Ê0more than one script system installed.  TextEdit°dONLNda<m9(âZ4uses the Script Manager to support such systems and °dONLNdJa9m)˝-now exhibits the correct behavior for editing°dONLNdxm<y2(ïZ5and displaying text in multiple styles and different °dONLNd≠m2y)ˆ.scripts.  Multiple scripts can even exist on a°dONLNd‹y<Ö˘(°Z_single line due to TextEdit’s use of the Script Manager.  The new version of TextEdit in 6.0.5:°dONLNd<ëNùR+•°dONLNd>ë[ùË)
  5210. handles mixed-directional text°dONLNd]ùN©R(≈l•°dONLNd_ù[©¸)
  5211.  synchronizes keyboards and fonts°dONLNdÄ©NµR(—l•°dONLNdÇ©[µÏ)
  5212. handles double-byte characters°dONLNd°µN¡R(›l•°dONLNd£µ[¡+)
  5213. *determines word boundaries and line breaks°dONLNdŒ¡NÕR(Èl•°dONLNd–¡[Õ;)
  5214. /provides outline highlighting in the background°dONLNdÕNŸR(ıl•°dONLNdÕ[Ÿ&)
  5215. )buffers text for performance improvements°dONLNd,ŸNÂR(l•°dONLNd.Ÿ[Âe)
  5216. ?permits left justification in right-to-left directional scripts°dONLNdnÂNÒR(
  5217. l•°dONLNdpÂ[Ò◊)
  5218. customizes word breaking°dONLNdâÒN˝R(l•°dONLNdãÒ[˝√)
  5219. customizes measuring°dONLNd†    <fi(1Z!Refer to the TextEdit chapter in °dONLNd¡    fi1)¢Inside Macintosh°dONLNd—    1:)S, °dONLNd”    :)    (Volume VI, for detailed documentation on°dONLNd¸<!{(=Z
  5220. TextEdit 3.0.
  5221. °dONLNd
  5222. 9<H*'The LineStarts Array and nLines
  5223. °dONLNd*U<aQ*The °dONLNd.TQ`ó)
  5224. LineStarts°dONLNd8UóaÙ)F array is a field in a °dONLNdOUÙa)]>TextEdit record that contains the offset position of the first°dONLNdéa<mv(âZ
  5225. character of °dONLNdõavmè):each°dONLNdüaèmô)9 line.  This array has the following boundary conditions: ¶X¶/
  5226. (ªZTextEdit Technicalities(ª1) of 4ˇ°¿Ù%%DSIDICT:_cv
  5227. currentdict /bu known {bu}if
  5228. userdict /_cv known not{userdict /_cv 30 dict put}if
  5229. _cv begin
  5230. /bdf{bind def}bind def
  5231. currentscreen/cs exch def/ca exch def/cf exch def
  5232. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5233. /ss{//cf //ca //cs setscreen}bdf
  5234. /stg{ss setgray}bdf
  5235. /strgb{ss setrgbcolor}bdf
  5236. /stcmyk{ss cvcmyk}bdf
  5237. /min1{dup 0 eq{pop 1}if}bdf
  5238. end
  5239. currentdict /bn known {bn}if
  5240. †øí◊#ˇ ˇˇˇˇ#◊ 
  5241. d,Times
  5242. .+6-Macintosh Technical Notes /4/
  5243. °dONLNd*).+•°dONLNd7)¶)
  5244. It is a zero-based array.°dONLNd**6.(RH•°dONLNd*76:)
  5245. 8The last entry in the array must have the same value as ,
  5246. Courier°dONLNdV):5r(RXteLength°dONLNd^*r6v)8.°dONLNd`6*B.(^H•°dONLNdb67B)
  5247. (The maximum number of entries is 16,000.°dONLNdãO[ˇ(w62To determine the length of a line you can use the °dONLNdΩOˇ[ä)Áinformation contained in the °dONLNd⁄NäZ–)ã
  5248. lineStarts°dONLNd‰O–[Ï)F array°dONLNdÎ\h.(Ñ6and °dONLNdÔ[.gX)nLines°dONLNdı\Xhø)*H.  For example, if you want to determine the length of line n, subtract °dONLNd=\øhÏ(Ñ›    the value°dONLNdGhtN(ê6Dcontained in entry n of the array from the value in the entry (n+1):
  5249.     °dONLNdåÄãg*C    lengthOfLineN := myTE^^.lineStarts[n+1] - myTE^^.lineStarts[n];
  5250. °dONLNd–ó£*2The terminating condition for this measurement is °dONLNdó£#)Ìwhen °dONLNdñ#¢â)n = nLines + 1°dONLNdóâ£Ï)f.  It is important not°dONLNd,£ظ(À61to change the information contained in the array.
  5251. °dONLNd^«÷[*'    TESysJust
  5252. °dONLNdh‚ÓW*    TESysJust°dONLNdq„WÔm)? is a °dONLNdw„mÔÏ)Plow-memory global that specifies the system justification.  The default value of°dONLNd»Ô˚~(6Nthis global is normally based on the system script.  It is -1 when a system’s °dONLNdÔ~˚Ï(údefault line direction is°dONLNd0˚“(#6dright to left, and 0 for a default left-to-right line direction.  Applications may change the value °dONLNdî˚“Ï(#using°dONLNdö*(06the °dONLNdû*ü)Script Manager routine °dONLNdµüÂ)u
  5253. SetSysJust°dONLNdøÂÏ)F5; however, these applications should save the current°dONLNdı …(<6%value before using it and restore it °dONLNd… Ï)±:before exiting the application or processing a MultiFinder°dONLNdU ,ÿ(H6"suspend event.  The current value °dONLNdw ÿ,Ï)¿0may be obtained using the Script Manager routine°dONLNd®,8^(U6
  5254. GetSysJust°dONLNd≤-^9b)F.
  5255. °dONLNd¥Q`≥(|6Forcing Text Direction
  5256. °dONLNdÀmy*/The original TextEdit documentation introduced °dONLNd˙lxL)Ó
  5257. _TESetJust°dONLNdmLyk)F with °dONLNd
  5258. mkyÏ)three possible choices for°dONLNd%zÜX(¢6justification:  °dONLNd5yXÖû)@
  5259. teJustLeft°dONLNd?zûܰ)F °dONLNd@z°Ü∑)(0), °dONLNdEy∑Ö ) teJustCenter°dONLNdQz Ü:)T
  5260.  (1), and °dONLNd[y:Öá)/ teJustRight°dONLNdfzáÜÏ)M (-1).  These choices°dONLNd|Üí›(Æ6,are appropriate for script systems that are °dONLNd®Ü›íÏ)≈9read from left to right.  However, in script systems that°dONLNd‚íû(∫6;are read from right to left, text is incorrectly displayed °dONLNdíûÏ(∫7.as left justified in dialog boxes and in other°dONLNdLû™t(Δ6Lareas of applications where users cannot explicitly set the justification.  °dONLNdòût™Ï(ΔíTo fix this problem, the°dONLNd±´∑Q(”6 behavior of °dONLNdΩ™Q∂ó)9
  5261. teJustLeft°dONLNd«´ó∑≠)F has °dONLNdô≠∑Ï)Bchanged to match the line direction of the system in use, which is°dONLNd∏ƒq(‡6the value stored in °dONLNd#∑q√∞)Y    TESysJust°dONLNd,∏∞ƒÅ)?,.  Another constant has been added to allow °dONLNdX∏ŃÏ)—an application to force°dONLNdp≈—j(Ì6left justification:  °dONLNdÖƒj–∑)R teForceLeft°dONLNdê≈∑—Ó)M
  5262.  (-2).  This °dONLNdù≈Ó—Ï)75constant has been available for some time, but it has°dONLNd”—›G(˘6    not been °dONLNd‹—G›Ï)/Pdocumented until now.  If your application does not allow the user to change the°dONLNd-fiͱ(6"justification, then it should use °dONLNdO›±Ș)ô
  5263. teJustLeft°dONLNdYfi˜Íw)F; if it does, then it should °dONLNdvfiwÍå)Äuse °dONLNdz›åÈŸ) teForceLeft°dONLNdÖfiŸÍÏ)M for°dONLNdä͈e(6left justification.
  5264. °dONLNdû)*'&A Little More on Redraw in _TESetStyle
  5265. °dONLNd≈*66*If the °dONLNdÃ)65`)redraw°dONLNd“*`6Ω)* parameter used in °dONLNdÂ)Ω5
  5266. )] _TESetStyle°dONLNd*
  5267. 6)M is °dONLNdÙ)5=)FALSE°dONLNd˘*=6Ï)#%, line breaks, line heights, and line°dONLNd    6B$(^6;ascents are not recalculated.  Therefore a succeeding call °dONLNd    Z6$BÏ(^B*to a routine using any of this information°dONLNd    ÖCON(k6Ddoes not reflect the new style information.  For example, a call to °dONLNd    …BNN¢(kl _TEGetHeight°dONLNd    ’C¢OÏ)T (which returns°dONLNd    ÂP\√(x6%a total height between two specified °dONLNd
  5268.  
  5269. P√\ü)´0lines) uses the line height set previous to the °dONLNd
  5270. :Oü[Ï)‹ _TESetStyle°dONLNd
  5271. F]ia(Ö6call.  A call to °dONLNd
  5272. W\ahß)I
  5273. _TECalText°dONLNd
  5274. a]ßi})F. is necessary to update this information.  If °dONLNd
  5275. è\}hß)÷redraw°dONLNd
  5276. ï]ßiπ)* is °dONLNd
  5277. ô\πh’)TRUE°dONLNd
  5278. ù]’iÏ), the ¶4¶
  5279. (ª62) of 4(ªúTextEdit Technicalitiesˇ
  5280. ◊#ˇ ˇˇˇˇ#◊ 
  5281. d,Times
  5282. .+Z-åDeveloper Support Center                                                                                                          April 1990 /X//
  5283. °dONLNd<*Δ*current style information is °dONLNdΔ*£)ä,reflected. This behavior also holds for the ,
  5284. Courier°dONLNdI£)Õ)›redraw°dONLNdOÕ*)*
  5285.  parameter in°dONLNd]*<6•(SZ_TEReplaceStyle°dONLNdl+•7©)i.
  5286. °dONLNdnO<^°(zZ
  5287. TEDispatchRec
  5288. °dONLNd|k<w≤*CThere is currently space reserved for four documented hooks in the °dONLNdøj≤v
  5289. (ì–
  5290. TEDispatchRec°dONLNdÃk
  5291. w)[:°dONLNdœw<É{(†Z    TEEolHook°dONLNdÿx{ÑÇ)?, °dONLNd⁄wÇÉœ) TEWidthHook°dONLNdÂxœÑ◊)M, °dONLNdÁw◊É)
  5292. TEDrawHook°dONLNdÒxÑ6)F and °dONLNdˆw6Éë)
  5293. TEHitTestHook°dONLNdxëÑ)[.  The space beyond these°dONLNdÑ<êÔ(¨Z_hooks is reserved, and any attempt to use this private area results in corrupted TextEdit data.
  5294. °dONLNd}®<∑…*'Custom Word Breaks
  5295. °dONLNdêƒ<–q*
  5296. A problem °dONLNdöƒq–a)51exists in one of TextEdit’s advanced procedures, °dONLNdÀ√aœµ) SetWordBreak°dONLNd◊ƒµ–)T.  The current glue°dONLNdΖ<‹œ(¯ZVcode does not preserve the state of the registers correctly; however, the solution is °dONLNdA–œ‹(¯Ìfairly simple.°dONLNdQ›<Èê(ZInstead of calling °dONLNdd‹êˉ)T SetWordBreak°dONLNdp›‰È¥)T+ and passing a pointer to your custom word °dONLNdõ›¥È)–break routine, pass°dONLNdØÈ<ı+(Z4the pointer to your external glue which should call °dONLNd„È+ı)Ô-your custom word break routine.  Following is°dONLNdı< (Z3the glue code that correctly handles the registers:
  5297.     °dONLNdE<$Ê*#"WordBreakProc    PROC       EXPORT°dONLNdh-<8ö*F                 IMPORT     MYWORDBREAK        ;Must be uppercase here°dONLNdØ7<B*
  5298. *                 MOVEM.L    D1-D2/A1,-(SP)°dONLNd⁄A<L|*
  5299. @                 CLR.W      -(SP)              ;Space for result°dONLNdK<Vï*
  5300. E                 MOVE.L     A0,-(SP)           ;Move the ptr to stack°dONLNdaU<`©*
  5301. I                 MOVE.W     D0,-(SP)           ;Move the charpos to Stack°dONLNd´_<jˇ*
  5302. '                 JSR        MYWORDBREAK°dONLNd”i<tY*
  5303. 9                 MOVE.W     (SP)+,D0           ;Set Z bit°dONLNd
  5304. s<~*
  5305. *                 MOVEM.L    (SP)+,D1-D2/A1°dONLNd8}<à†*
  5306.                  RTS°dONLNdMë<ú•*                 ENDP
  5307. °dONLNdcß<≥˝**An external declaration is also necessary:
  5308.     °dONLNdéø< ¬*N    FUNCTION WordBreakProc( text: Ptr; charPos: INTEGER ) : BOOLEAN; EXTERNAL;
  5309. °dONLNd›’<·Ü*Ias is the function itself.  One thing that should be noted is that it is °dONLNd&’Ü·(˝§not really necessary to have°dONLNdC·<Ìâ(
  5310. Z MyWordBreak°dONLNdN‚âÓ,)M! boolean, but rather to have the °dONLNdo·,Ì3)£Z°dONLNdp‚3ÓÈ)& bit set properly.  The result of the °dONLNdñ‚ÈÓ)∂function°dONLNdüÓ<˙#(Z-should be zero when you do not want a break; °dONLNdÃÓ#˙)Á0otherwise, a non-zero value indicates a break is°dONLNd˝˙<b("Zdesired.
  5311.     °dONLNd<ê*D    FUNCTION MyWordBreak( text : Ptr; charPos : INTEGER ) : INTEGER;°dONLNdK<'Ê*
  5312. "    { Your word break code here. }
  5313. °dONLNdn2<><*7For more information, refer to the TextEdit chapter of °dONLNd•2<>ç(ZZInside Macintosh°dONLNdµ2ç>⁄)Q, Volume I-380. ¶X¶/
  5314. (ªZåTextEdit Technicalities                                                                                                                     (ª3) of 4ˇ    ∏◊#ˇ ˇˇˇˇ#◊ 
  5315. d,Times
  5316. .+6-Macintosh Technical Notes /4/ 
  5317. °dONLNd)8∏*'Static and Editable Text
  5318. °dONLNdDP”*^The Dialog Manager depends on TextEdit to display text in dialog boxes.  For an editable text °dONLNdwD”PÏ(lÒfield,°dONLNd~Q]≤(y6 the Dialog Manager simply calls ,
  5319. Courier°dONLNdûP≤\Ò)ö    _TEUpdate°dONLNdßQÒ]√)?..  Before making this call, it may double the °dONLNd’Q√]Ï)“width of°dONLNdfi]i¨(Ö6"the rectangle to contain the text °dONLNd]¨iÏ)îFif the height of the rectangle is sufficient for only one line and the°dONLNdGjvX(í6line direction °dONLNdVjXvñ)@
  5320. specified by °dONLNdciñu’)>    TESysJust°dONLNdlj’vÏ)?< is left to right.  In this case, the Dialog Manager extends°dONLNd©vǯ(û61the rectangle on the right.  Note, however, this °dONLNd⁄v¯ÇÏ)‡3does not occur when your line direction is right to°dONLNdÇé+(™6left.°dONLNdõß{*For static text items, °dONLNd+ö{¶≥)c_TextBox°dONLNd3õ≥ß)8 is used instead.  °dONLNdFõßÏ)R/When the display rectangle is not large enough.°dONLNdvß≥P(–6_TextBox°dONLNd~®P¥ÿ)8 clips the text to the size of °dONLNdù®ÿ¥Ï)à8the specified rectangle.  To avoid the clipping problem,°dONLNd÷¥¿∫(‹6"simply make the display rectangle °dONLNd¯¥∫¿Ï)¢Blarger.  If your dialog box contains both static and editable text°dONLNd;¿ÃM(Ë6Citems, the difference in the text handling may appear inconsistent.°dONLNd¸Ç*0Further Reference: 4 °dONLNdí˝*    .+
  5321. •°dONLNdî˝<    ç)Inside Macintosh°dONLNd§˝ç    )Q, Volumes I,V & VI, TextEdit°dONLNd¡    *.(1H•°dONLNd√    <ç)Inside Macintosh°dONLNd”    ç()Q, Volume V, The Script Manager°dONLNdÚ*!.(=H•°dONLNdÙ<!ë)Inside Macintosh,°dONLNdë!')U Volume I, The Dialog Manager°dONLNd#!*-.(IH•°dONLNd%!<-¨)M.TE.TestEditChanges ¶4¶
  5322. (ª64) of 4(ªúTextEdit Technicalitiesˇà◊#ˇ ˇˇˇˇ#◊†Ç 
  5323. /ZÅ#
  5324.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5325. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5326. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5327. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5328. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5329.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5330. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  5331. IR.°dONLNdn<Ń(õZ
  5332. TrueType Q&As
  5333. °dONLNdÄ<èr*Imaging°dONLNdÄcè˛(´ÅM.QD.TrueType.Q&As
  5334. °dONLNd)õ<ßt(√Z Revised by:°dONLNd5õÑߡ)HDeveloper Support Center°dONLNdNõæß˛(√‹ October 1992°dONLNd[ß<≥q(œZ Written by:°dONLNdgßÑ≥ˇ)HDeveloper Support Center°dONLNdÄßæ≥˛(œ‹ October 1990°dONLNdçø<À⁄(ÁZThis Technical Note contains a °dONLNd¨ø⁄À˛)û9collection of Q&As relating to a specific topic—questions°dONLNdÊÀ<◊†(ÛZGyou’ve sent the Developer Support Center (DSC) along with answers from °dONLNd-À†◊˛(Ûæthe DSC engineers.°dONLNd@◊<„u(ˇZ
  5335. While DSC °dONLNdJ◊u„˛)9Lengineers have checked the Q&A content for accuracy, the Q&A Technical Notes°dONLNdó„<Ôq( Z don’t have °dONLNd¢„qÔ˛)5Qthe editing and organization of other Technical Notes. The Q&A function is to get°dONLNdÙÔ<˚Ÿ(Znew technical information and °dONLNdÔŸ˚˛)ù6updates to you quickly, saving the polish for when the°dONLNdI˚<(#Z,information migrates into reference manuals.°dONLNdv<k*:Q&As are now included with Technical Notes to make access °dONLNd∞k˛(;âto technical updates easier for°dONLNd–<+.(GZ/you. If you have comments or suggestions about °dONLNdˇ.+˛)Ú*Q&A content or distribution, please let us°dONLNd*+<7\(SZknow °dONLNd/+\7˛) Iby sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical°dONLNdy7<Ci(_Z9questions about Q&A content to DEVSUPPORT for resolution.°dONLNd≥O<[«*NNew Q&As and Q&As revised this month are marked with a bar in the side margin."n  ÜXÜ
  5336. °dONLNdÄ<èp*4,SetPreserveGlyph and font glyph preservation
  5337. °dONLNd/è<õb* Written:°dONLNd8èàõ¨)L7/22/91°dONLNd@õ<ßÅ(√ZLast reviewed:°dONLNdOõàß¶)L8/1/92°dONLNdV≥<ø~(€ZBTrueType’s SetPreserveGlyph call with preserveGlyph set to “true” °dONLNdò≥~ø˛(€úworks as you’d expect for°dONLNd≤ø<ÀÁ(ÁZSTimes and Helvetica, but it has no effect on New York, Geneva, Monaco, or Chicago. °dONLNdøÁÀ˛(ÁWhy°dONLNd    À<◊˜(ÛZ$does SetPreserveGlyph work this way?°dONLNd.◊<„N* ___°dONLNd2Ô<˚*.Glyph preservation is a function of the font. °dONLNd`Ô˚˛)”1It turns out that Times and Helvetica have glyphs°dONLNdí˚<‡(#Z#that extend above the ascent line, °dONLNdµ˚‡˛)§8thereby enabling SetPreserveGlyph to have an effect on a°dONLNdÓ< (/Zparticular glyph. New York, °dONLNd
  5338.  ˛)é<Geneva, Monaco, and Chicago’s characters all fit between the°dONLNdG<–(;ZVascent and descent lines, and so do not need to be compressed to fit if preserveGlyph °dONLNdù–˛(;Ó
  5339. is true. A°dONLNd®<+(GZKfont must have glyphs extending above or below the ascent or descent lines °dONLNdÛ+˛(Gfor°dONLNd˜+<7Ê(SZ#SetPreserveGlyph to have an effect.
  5340. °dONLNdO<^Ÿ*'RealFont and TrueType
  5341. °dONLNd1^<jb* Written:°dONLNd:^àj¶)L9/4/91°dONLNdAj<vÅ(íZLast reviewed:°dONLNdPjàv¶)L8/1/92°dONLNdWÇ<ég(™Z;What is the story with RealFont and TrueType? I am finding °dONLNdíÇgé˛(™Öthat, of the standard System 7°dONLNd±é<öG(∂Z6fonts, only Symbol and Courier get a TRUE for 7 point.°dONLNdËö<¶N* ___ ◊X◊
  5342. **
  5343. TrueType Q&As(Ï1) of 3ˇ°¿Ù%%DSIDICT:_cv
  5344. currentdict /bu known {bu}if
  5345. userdict /_cv known not{userdict /_cv 30 dict put}if
  5346. _cv begin
  5347. /bdf{bind def}bind def
  5348. currentscreen/cs exch def/ca exch def/cf exch def
  5349. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5350. /ss{//cf //ca //cs setscreen}bdf
  5351. /stg{ss setgray}bdf
  5352. /strgb{ss setrgbcolor}bdf
  5353. /stcmyk{ss cvcmyk}bdf
  5354. /min1{dup 0 eq{pop 1}if}bdf
  5355. end
  5356. currentdict /bn known {bn}if
  5357. †øX◊#ˇ ˇˇˇˇ#◊ 
  5358. IR,Times
  5359. .+6-Macintosh Technical Notes /4/˘
  5360. °dONLNd)5s*$You are absolutely °dONLNd)s5⁄)[Icorrect with your observation of RealFont for size 7 and certain TrueType°dONLNd]5AR(]6 fonts. The °dONLNdh5RA⁄):Gexplanation is hidden in “The TrueType Font Format Specification” (APDA°dONLNd∞AMå(i6M0825LL/A), page 227:°dONLNdΔYe-*The °dONLNd Y-e⁄)U“head” FontHeader table contains a field “lowestRecPPEM,” which indicates the “lowest°dONLNd eqí(ç6Mrecommended pixel number per Em,” or, in other words, the “smallest readable °dONLNdmeíq⁄(ç∞size in pixels.”°dONLNd~q}π(ô6WAs it turns out, the Font Manager in its wisdom uses this information for the value it °dONLNd’qπ}⁄(ô◊returns°dONLNd›}â•(•6Ufrom RealFont. Note that for higher resolution devices, a point size of 7 does *not* °dONLNd2}•â⁄(•√
  5361. correspond°dONLNd=âï˜(±63to 7 pixels; but as the unit “point” is 1/72 inch, °dONLNdpâ˜ï⁄)fl/and the screen resolution is (approximately) 72°dONLNd†ï°˝(Ω64dpi, the result corresponds to reality in this case.°dONLNd’≠πS*?The value for lowestRecPPEM can be arbitrarily set by the Font °dONLNd≠Sπ⁄(’qdesigner. We all know that°dONLNd/π≈Ï(·6,small point sizes on low-resolution devices °dONLNd[πÏ≈⁄)‘0never look “great,” and even less so for outline°dONLNdå≈—Ã(Ì6Sfonts. Courier and Symbol have lowestRecPPEM = 6, while the other outline fonts in °dONLNdfl≈×⁄(ÌÍthe°dONLNd„—›s(˘6ESystem have lowestRecPPEM = 9. This doesn’t really mean that Courier °dONLNd(—s›⁄(˘ëand Symbol in size 7°dONLNd=›Èë(6M(TrueType) look better than Times or Helvetica under the same conditions. It °dONLNdä›ëÈ⁄(Ømeans the font°dONLNdôÈı(6Jdesigner had higher standards (or was in a different mood) when he choose °dONLNd„Èı⁄(ùlowestRecPPEM =°dONLNdÛı"(69.
  5362. °dONLNdˆ(Ó*'Where to find OutlineAccessLib
  5363. °dONLNd(4>* Written:°dONLNd(d4à)L12/9/91°dONLNd&4@](\6Last reviewed:°dONLNd54d@Ç)L8/1/92°dONLNd<LX¨(t6TIs the OutlineAccessLib library, which will provide standardized access routines to °dONLNdêL¨X⁄(t TrueType°dONLNdôXd(Ä65font outline bezier data, available yet? I have been °dONLNdŒXd⁄)Ì-unable to find this in the last few Developer°dONLNd¸dp¬(å6 CDs or the MPW 3.2 C release CD.°dONLNdp|** ___°dONLNd!àîÆ*The OutlineAccessLib is now °dONLNd=àÆî⁄)ñ9available (although somewhat disguised and hidden) on the°dONLNdwî†≥(º6UDeveloper CD Vol. X (and later); it is included in the code accompanying the article °dONLNdÃî≥†⁄(º—“Curves°dONLNd‘†¨ß(»6ahead” in issue #8 of develop.
  5364. °dONLNdÛƒ”q*'4SetOutlinePreferred affects only calling application
  5365. °dONLNd(”fl>* Written:°dONLNd1”dflÇ)L3/9/92°dONLNd8flÎ](6Last reviewed:°dONLNdGfldÎÇ)L8/1/92°dONLNdN˜œ(6WIs the property that is managed by SetOutlinePreferred and GetOutlinePreferred kept on °dONLNd•˜œ⁄(Ìan°dONLNd®≈(+6%application-by-application basis? In °dONLNdÕ≈⁄)≠9other words, will calling SetOutlinePreferred affect only°dONLNdä(76my application? As the °dONLNdä⁄)rDcurrent value of outlinePreferred is saved in a PICT, will playing a°dONLNdc'\(C6 PICT affect °dONLNdo\'⁄)DIthe playing application’s current outlinePreferred setting? I assume that°dONLNdπ'36(O6AoutlinePreferred is not an attribute of a GrafPort; is this true?°dONLNd˚3?** ___°dONLNdˇKW©* The outlinePreferred setting is °dONLNd    K©W⁄)ë?stored as a low-memory global value for your application. It is°dONLNd    _Wc…(6Wsaved and restored during context switches, so it only effects your application and no °dONLNd    ∂W…c⁄(Áone°dONLNd    ∫co7(ã6else’s.°dONLNd    ¬{áÿ**DrawPicture should not alter the state of °dONLNd    Ï{ÿá⁄)¿4the global for you. While DrawPicture internally may°dONLNd
  5366. !áì(Ø66set or reset this value, it’s supposed to put it back °dONLNd
  5367. Wáì⁄)˜(the way it found it when it is done. So,°dONLNd
  5368. Äìüf(ª6Jplaying a PICT will not affect the current application’s outline settings. ◊4◊˘
  5369. *12) of 3(ϵ
  5370. TrueType Q&Asˇ¥◊#ˇ ˇˇˇˇ#◊ 
  5371. IR,Times
  5372. .+Z-Developer Support Center(-Ê October 1992 /X/
  5373. °dONLNd<)ê(EZHAnd no, OutlinePreferred is not part of a grafport (as mentioned above.)
  5374. °dONLNdIA<Pê*'/QuickDraw doesn’t draw ASCII 32 ($20) character
  5375. °dONLNdyP<\b* Written:°dONLNdÇPà\¨)L3/18/92°dONLNdä\<hÅ(ÑZLast reviewed:°dONLNdô\àh¶)L8/1/92°dONLNd†t<Ä—(úZQMy TrueType font has all 256 characters defined with a unique glyph. I have been °dONLNdÒt—IJ(úÔ    unable to°dONLNd˚Ä<åÄ(®Z
  5376. draw the $20 °dONLNdÄÄå˛)DI(space) character. DrawChar, DrawText, DrawString and DrawJust all ignore°dONLNdRå<òê(¥ZIthis character in the font and draw a blank character. How can I draw it?°dONLNdúò<§N* ___°dONLNd†∞<ºÓ*$Unfortunately, the problem with the °dONLNdƒ∞Óº˛)≤6space character not being drawn is hard-coded into the°dONLNd˚º<»2(‰Z/text-drawing routine in the core of QuickDraw. °dONLNd*º2»˛)ˆ$ASCII 32 is always “optimized away,”°dONLNdO»<‘Ç(Zregardless of °dONLNd]»Ç‘˛)FIthe font being used, regardless of the particular circumstances. The only°dONLNdß‘<‡Ä(¸ZBworkaround is to put the corresponding character elsewhere in the °dONLNdÈ‘ć˛(¸ûASCII character encoding°dONLNd‡<Ï3(Z9(or, if this is not possible, to use an additional font).°dONLNd<¯<–*TYou are lucky that TrueType fonts always render the ASCII code 13 (carriage return) °dONLNdꯖ˛( Ó if it has a°dONLNdú<[(,Zglyph °dONLNd¢[˛)Uin the font; for bitmap fonts, if the character drawing happens with scaling, or with°dONLNd¯<Ë(8ZVforeground/background colors different from black/white, even the CHR(13) drawing has °dONLNdN˲(8been°dONLNdS<(ä(DZoptimized away. ◊X◊
  5377. (ÏZ
  5378. TrueType Q&As(Ï3) of 3ˇN◊#ˇ ˇˇˇˇ#◊†Ç 
  5379. /ZÅ#
  5380.     0Ià:µú9"{    ˇˇˇˇˇˇˇˇ#†ƒ°d
  5381. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  5382. .R…R…+]BNew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  5383. ({ïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  ffZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  5384. 0(UÔ†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  5385.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  5386. (Z\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  5387. IR.°dONLNdˇˇ(ßZ"How to Construct Word-Break Tables
  5388. °dONLNdˇˇ*Text°dONLNdˇˇ(∑zM.TE.WordBreakTables
  5389. °dONLNdˇˇ(œZ Revised by:°dONLNdˇˇ(œ„
  5390. March 1988°dONLNdˇˇ(€Z Written by:°dONLNdˇˇ)H
  5391. Mark Davis°dONLNdˇˇ(€œ
  5392. November 1987°dONLNdˇˇ(ÛZNThis technical note describes how to construct auxiliary break tables for use °dONLNdˇˇ(ÛÒwith the,
  5393. Courier°dONLNdˇˇ(ZFindWord°dONLNdˇˇ)8 routine in the Script Manager. X
  5394. °dONLNdˇˇ(4ZConstructing break tables
  5395. °dONLNdˇˇ*The °dONLNdˇˇ)FindWord°dONLNdˇˇ)8  algorithm °dONLNdˇˇ)3>finds word boundaries by determining where words should not be°dONLNdˇˇ(YZ*broken. For example, “re-do” is one word: °dONLNdˇˇ)’/it should not be broken at the hyphen. In other°dONLNdˇˇ(eZ    words, a °dONLNdˇˇ)-Usequence of the form: (letter, hyphen, letter) should not be broken between the first°dONLNdˇˇ(qZRand second or second and third character. This is called a continuation sequence. °dONLNdˇˇ(qŸ
  5396. The algorithm°dONLNdˇˇ(~Z used by the °dONLNdˇˇ)<FindWord°dONLNdˇˇ)8B routine allows for continuation sequences of lengths one, two and°dONLNdˇˇ(äZ[three. Examples of a sequence of length two include (letter, letter), or (number, number). °dONLNdˇˇ(äFor a°dONLNdˇˇ(óZ=length of one, there is only one sequence, consisting of the °dONLNdˇˇ(óscharacters of type °dONLNdˇˇ)Y nonBreaking°dONLNdˇˇ)M:°dONLNdˇˇ(£ZLthese characters are never separated from preceding or following characters.°dONLNdˇˇ*For °dONLNdˇˇ)Zmost scripts, this information about continuation sequences is packed into a table for use°dONLNdˇˇ(»Zby the °dONLNdˇˇ) FindWord°dONLNdˇˇ)8& algorithm. (For complex scripts like °dONLNdˇˇ)∞'Japanese, a different algorithm is used°dONLNdˇˇ(‘ZPfor portions of the script.) The default break tables for a given script can be °dONLNdˇˇ(‘Œoverridden by a°dONLNdˇˇ(·Zuser-specified °dONLNdˇˇ)F
  5397. breakTable°dONLNdˇˇ)F< parameter, but should only be used for known scripts. That °dONLNdˇˇ(·is,°dONLNdˇˇ(ÓZbefore overriding the °dONLNdˇˇ)f
  5398. breakTable°dONLNdˇˇ)F2 parameter, the programmer should first check the °dONLNdˇˇ)Ó    script of°dONLNdˇˇ(˙Zthe current font.°dONLNdˇˇ*A break table consists of two °dONLNdˇˇ)åAsections, a 256 byte character type table followed by a character°dONLNdˇˇ(Z
  5399. triple table. ◊X◊
  5400. *Œ"How to Construct Word-Break Tables(Ï1) of 4ˇ°¿Ù%%DSIDICT:_cv
  5401. currentdict /bu known {bu}if
  5402. userdict /_cv known not{userdict /_cv 30 dict put}if
  5403. _cv begin
  5404. /bdf{bind def}bind def
  5405. currentscreen/cs exch def/ca exch def/cf exch def
  5406. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  5407. /ss{//cf //ca //cs setscreen}bdf
  5408. /stg{ss setgray}bdf
  5409. /strgb{ss setrgbcolor}bdf
  5410. /stcmyk{ss cvcmyk}bdf
  5411. /min1{dup 0 eq{pop 1}if}bdf
  5412. end
  5413. currentdict /bn known {bn}if
  5414. †ø,,◊#ˇ ˇˇˇˇ#◊ 
  5415. IR,Times
  5416. .+6-Macintosh Technical Notes /4/˘†Ç†å
  5417. <xÚµ
  5418. 4››&8°ñ@°öˇ˝†ò
  5419. ∂=∫?°dONLNdˇˇ+ÃΩbreak†ô†ó
  5420. "Dà"Dà4››Á84›Ê84›Ô˘8†ç†å
  5421. 4›ñfi8°ñ@°öˇ˝†òL°dONLNdˇˇ(ͪbreak†ô†ó
  5422. "Dà"Dà4›ñ†84›ü©84›®≤8†ç†å†††•°§
  5423.     "?%
  5424. #:###ÙÒ#Δ#ÌÒ#†£
  5425. <xÚµ
  5426. ˇˇˇˇˇˇˇˇÑd?%ïC?%&ˇ@%'ˇA&(ˇB'*ˇC()*+ˇD)*+-ˇE*+-.ˇF+,./ˇG/0ˇH,-01ˇI-.12ˇK23ˇL./34ˇN45ˇP/0ˇS56ˇT01ˇW67ˇ`78ˇc12ˇ{2389ˇÄ34ˇÇ9:ˇÑ45ˇÜ56:;ˇä67;<ˇã78ˇç89<=ˇé9:=>ˇè:;>?ˇê;=ˇë=>?@ˇí>AˇìABˇî@CˇïBCˇˇ"F+####################################################ˇ##ˇ#ˇ##ˇˇ##ˇˇ#ˇ#ˇ#ˇˇ#ˇ#ˇˇ#ˇˇ#ˇˇ#˛#ˇˇ#˛#ˇ˛#˛#ˇ˝#ˇ#˝#ˇ˝#˝#˝#¸#˝#¸#˝#¸#ˇ˝#˝#˝#ˇ˝#˛#ˇ˛#˛#ˇ˛#ˇ˛#ˇˇ#ˇ˛#ˇˇ#ˇˇ#ˇˇ#ˇˇ#ˇˇ#ˇ#ˇˇ#ˇˇ#ˇ#ˇ#ˇ#ˇ#ˇ##ˇˇ####################†°†††•°§
  5427. "Ô%
  5428. Ò#Δ#Ò##Ù#:#Ì#†£
  5429. <xÚµÑdô%ÔCôBCˇö@CˇõABˇú>Aˇù=>?@ˇû<=ˇü:<>?ˇ†9:=>ˇ°89<=ˇ¢78ˇ§67;<ˇß56:;ˇ©45ˇ¨9:ˇÆ34ˇ≥2389ˇ 12ˇŒ78ˇ◊67ˇŸ01ˇ€56ˇ›/0ˇfl45ˇ·./34ˇ‚23ˇ‰-.12ˇÊ,-01ˇÁ+,/0ˇË./ˇÈ*+-.ˇÍ)*+-ˇÎ()*+ˇÏ'*ˇÌ&(ˇÓ%'ˇÔ%&ˇˇ"Á+#ˇ#ˇ#˛#ˇ#˛#˛#˛#˛#˛#˝#˝#˝#˝#¸#˝#¸#˝#¸#˝#˝#˝#˝#ˇ#˝#˛#˛#˛#ˇ#˛#ˇ#ˇ#ˇ#ˇ#ˇ##ˇ#ˇ##ˇ##ˇ###ˇ##########ˇ###ˇ##ˇ##ˇ#ˇ##ˇ#ˇ#ˇ##ˇ##ˇ##ˇ###ˇ########ˇ###ˇ##ˇ##ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ##ˇ##ˇ##ˇ########ˇ###ˇ##ˇ##ˇ#ˇ##ˇ#ˇ#ˇ†°†ç°ñ¸°öˇ˝4†ò°dONLNdˇˇ(ôJCharacter Type Table†ô†ó†åTZ≤^∂TZ⁄^›TZ^†ç°ñ¸°öˇ˝ †ò∂°dONLNdˇˇ(P|$00†ô†ó°ñ¸°öˇ˝ †òí°dONLNdˇˇ*T$40†ô†ó°ñ¸°öˇ˝ †òn°dONLNdˇˇ*$42†ô†ó†å
  5430. 4óñ™fi    ˇˇˇˇˇˇˇˇ8°ñ@°öˇ˝†òJ°dONLNdˇˇ(§ªpunct†ô†ó
  5431. "Dà"Dà4óñ™†84óü™©84ó®™≤8†ç†å
  5432. 4gñzfi8°ñ@°öˇ˝†ò°dONLNdˇˇ(t∏number†ô†ó
  5433. "Dà"Dà4gñz†84güz©84g®z≤8†ç†å
  5434. 4©ñªfi8°ñ@°öˇ˝ †òŒ°dONLNdˇˇ+Aletter†ô†ó
  5435. "Dà"Dà4©ñª†84©üª©84©®ª≤8†ç†å
  5436. 4©›ª&8°ñ@°öˇ˝ †ò†°dONLNdˇˇ)Gletter†ô†ó
  5437. "Dà"Dà4©›ªÁ84©Êª84©Ôª˘8†ç°ñ¸°öˇ˝ †òr°dONLNdˇˇ(t|$30†ô†ó†å
  5438. 4g›z&8°ñ@°öˇ˝†òN°dONLNdˇˇ)Énumber†ô†ó
  5439. "Dà"Dà4g›zÁ84gÊz84gÔz˘8†ç†å
  5440. 4ó›™&8°ñ@°öˇ˝ †ò°dONLNdˇˇ+0letter†ô†ó
  5441. "Dà"Dà4ó›™Á84óÊ™84óÔ™˘8†ç†å
  5442. 4?ñRfi8°ñ@°öˇ˝†òÿ°dONLNdˇˇ(Lªblank†ô†ó
  5443. "Dà"Dà4?ñR†84?üR©84?®R≤8†ç†å
  5444. 4?›R&8°ñ@°öˇ˝†ò§°dONLNdˇˇ)Gbreak†ô†ó
  5445. "Dà"Dà4?›RÁ84?ÊR84?ÔR˘8†ç†å
  5446. ˇˇˇˇˇˇˇˇTÜ≤ä∂TÜ⁄ä›TÜä†ç†åTÕ≤—∂TÕ⁄—›TÕ—†ç°ñ|°öˇ˝ †òp°dONLNdˇˇ(Í|$FE†ô†ó0>ï&†É†Ç
  5447. 
  5448. Ç¿¨
  5449. 4Ö284ª2È8°ñ¸°öˇ˝ †ò∂*∂*°dONLNdˇˇ+KBletter†ô†ó°ñ¸°öˇ˝
  5450. †ò°dONLNdˇˇ)/wild†ô†ó
  5451. "Dà"Dà4Ö2è8°ñ¸°öˇ˝ †ò°dONLNdˇˇ(,õletter†ô†ó°ñ¸°öˇ˝-†ò°dONLNdˇˇ(£limit (# entries – 1)†ô†ó†å
  5452. 41ÖD841ªDÈ8
  5453. "Dà"Dà41ÖDè8†ç°ñ¸°öˇ˝
  5454. †ò°dONLNdˇˇ(>úwild†ô†ó°ñ¸°öˇ˝ †ò°dONLNdˇˇ)+letter†ô†ó°ñ¸°öˇ˝ †ò°dONLNdˇˇ)-letter†ô†ó†å†††•°§
  5455.     "
  5456. 
  5457. #:###ÙÒ#Δ#ÌÒ#†£
  5458. 
  5459. Ç¿¨
  5460. ˇˇˇˇˇˇˇˇÑd
  5461. c3
  5462. ˇˇˇˇˇˇˇˇ ˇ !ˇ!"ˇ"#ˇ#$ˇ$%ˇ ˇ %&ˇ# !ˇ%&'ˇ.'(ˇ1!"ˇH"#()ˇM#$ˇP)*ˇR$%ˇT%&*+ˇX&'+,ˇY'(ˇ[(),-ˇ\)*-.ˇ]*+./ˇ^+-ˇ_-./0ˇ`.1ˇa12ˇb03ˇc23ˇˇ"###################################################ˇ###ˇ#ˇ##ˇˇ##ˇˇ#ˇ#ˇ#ˇˇ#ˇ#ˇˇ#ˇˇ#ˇˇ#˛#ˇˇ#˛#ˇ˛#˛#ˇ˝#˛#˝#ˇ˛#˝#¸#˝#˝#¸#˝#¸#ˇ˝#˝#˝#ˇ˛#˝#ˇ˛#˛#ˇ˛#ˇ˛#ˇˇ#ˇ˛#ˇˇ#ˇˇ#ˇˇ#ˇˇ#ˇˇ#ˇˇ#ˇ#ˇˇ#ˇ#ˇ#ˇ#ˇ#ˇ##ˇˇ####################†°†††•°§
  5463. "º
  5464. Ú#≈#Ú##Ù#;#Ì#†£
  5465. 
  5466. Ç¿¨Ñhfº3f23ˇg13ˇh01ˇi/012ˇj./01ˇk-./0ˇl,-ˇm*,./ˇn)*-.ˇo(),-ˇp'(ˇq&'+,ˇu%&*+ˇw$%ˇy)*ˇ{#$ˇÅ"#()ˇò!"ˇõ'(ˇ§&'ˇ¶ !ˇ®%&ˇ´ ˇ≠$%ˇØ#$ˇ∞"#ˇ≤!"ˇ≥ !ˇµ ˇ∂ˇ∑ˇ∏ˇπˇ∫ˇªˇºˇˇ"µ#ˇ#˛#ˇ#˛#ˇ#˛#˛#˝#˛#˝#˝#˝#˝#˝#¸#˝#¸#˝#˝#˝#˝#˝#˛#˛#˛#˛#˛#˛#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ##ˇ#ˇ##ˇ###ˇ###########ˇ###ˇ##ˇ##ˇ#ˇ##ˇ#ˇ#ˇ##ˇ##ˇ##ˇ###ˇ########ˇ###ˇ##ˇ##ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ#ˇ##ˇ##ˇ##ˇ##########ˇ##ˇ##ˇ##ˇ#ˇ#ˇ##ˇ†°†ç°ñ¸°öˇ˝6†ò°dONLNdˇˇ+H'Character Triple Table†ô†ó†å
  5467. 4yÖå    ˇˇˇˇˇˇˇˇ84yªåÈ8
  5468. "Dà"Dà4yÖåè8†ç°ñ¸°öˇ˝†ò°dONLNdˇˇ(áînumber†ô†ó°ñ¸°öˇ˝†ò°dONLNdˇˇ)7dot†ô†ó°ñ¸°öˇ˝†ò°dONLNdˇˇ)"number†ô†ó†å
  5469. 4CÖV84CªVÈ8
  5470. "Dà"Dà4CÖVè8†ç°ñ¸°öˇ˝†ò°dONLNdˇˇ(Pïhyphen†ô†ó°ñ¸°öˇ˝ †ò°dONLNdˇˇ)2letter†ô†ó°ñ¸°öˇ˝
  5471. †ò°dONLNdˇˇ).wild†ô†ó†å
  5472. 4UÖh84UªhÈ8
  5473. "Dà"Dà4UÖhè8†ç°ñ¸°öˇ˝ †ò°dONLNdˇˇ(bõletter†ô†ó°ñ¸°öˇ˝†ò°dONLNdˇˇ)&hyphen†ô†ó°ñ¸°öˇ˝ †ò°dONLNdˇˇ)3letter†ô†ó†å
  5474. 4gÖz84gªzÈ8
  5475. "Dà"Dà4gÖzè8†ç°ñ¸°öˇ˝
  5476. †ò°dONLNdˇˇ(túwild†ô†ó°ñ¸°öˇ˝ †ò°dONLNdˇˇ)+letter†ô†ó°ñ¸°öˇ˝†ò°dONLNdˇˇ)'hyphen†ô†ó†å
  5477. ˇˇˇˇˇˇˇˇTû¶¢©TûŒ¢“Tû˜¢˙†ç BÑB xÑx Ñ0 Ñæ†É
  5478. IR°dONLNdˇˇ(·6The character type table is °dONLNdˇˇ)}Aindexed by the character’s ASCII code and contains one type value°dONLNdˇˇ(Ì6for each character. The °dONLNdˇˇ)sDcharacter types in the table are limited to values between 1 and 31.°dONLNdˇˇ(˙6.There are two distinguishing values: the type ,
  5479. Courier°dONLNdˇˇ)÷ nonBreaking°dONLNdˇˇ)M# (= 1) indicates that the character°dONLNdˇˇ(66is non-breaking; it always continues a word. The type °dONLNdˇˇ(@wild°dONLNdˇˇ) (=0) indicates that °dONLNdˇˇ)_
  5480. the character°dONLNdˇˇ(6may °dONLNdˇˇ)Vor may not break, depending on information in the character triple table, as described°dONLNdˇˇ(6^below.  Otherwise, the choice of numbers to represent character types is completely arbitrary.°dONLNdˇˇ*For °dONLNdˇˇ)Qexample, the following in MPW Assembler defines character types for use in a word°dONLNdˇˇ(7Ù-°dONLNdˇˇ(D6!selection break table, then sets °dONLNdˇˇ)í3up a character type table using an assembly macro (°dONLNdˇˇ)˚setByte°dONLNdˇˇ)1)°dONLNdˇˇ(P6    to store °dONLNdˇˇ)(Scharacter type values in an array.  (Note that the character types could  have been°dONLNdˇˇ(]6!defined with equate definitions (°dONLNdˇˇ)úEQU°dONLNdˇˇ)), °dONLNdˇˇ) 6rather than using the record structure.)   Writing the°dONLNdˇˇ(i6(setByte macro is left as an exercise to °dONLNdˇˇ)≥:the reader. Note that the break value is the default. This°dONLNdˇˇ(u6Fvalue is not distinguished, but should have no continuation sequences.
  5481.     °dONLNdˇˇ*=;============================================================°dONLNdˇˇ*
  5482. charWordRec°dONLNdˇˇ)lrecord°dONLNdˇˇ)H0°dONLNdˇˇ(†6wild°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$; constant! not in char table.°dONLNdˇˇ(™6nonbreak°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$; constant! non-breaking space.°dONLNdˇˇ(¥6letter°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$
  5483. ; letters.°dONLNdˇˇ(æ6number°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$    ; digits.°dONLNdˇˇ(»6break°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$; always breaks. ◊4◊˘
  5484. (Ï62) of 4(Ïb"How to Construct Word-Break Tablesˇ 6◊#ˇ ˇˇˇˇ#◊ 
  5485. IR,Times
  5486. .+Z-Developer Support Center(-Ï
  5487. March 1988 /X/,
  5488. Courier
  5489.     °dONLNdˇˇ(DZ    midLetter°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$; a'a.°dONLNdˇˇ(NZ    midLetNum°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$
  5490. ; a'a 1'1.°dONLNdˇˇ(XZpreNum°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$    ; $, etc.°dONLNdˇˇ(bZpostNum°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$    ; %, etc.°dONLNdˇˇ(lZmidNum°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$; 1,1.°dONLNdˇˇ(vZ    preMidNum°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$; .1234.°dONLNdˇˇ(ÄZblank°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$; spaces and tabs.°dONLNdˇˇ(äZcr°dONLNdˇˇ)lds.b°dONLNdˇˇ)H1°dONLNdˇˇ)$; add carriage return°dONLNdˇˇ(îΔendr°dONLNdˇˇ(ûZ=;============================================================°dONLNdˇˇ+$
  5491. with°dONLNdˇˇ)H charWordRec°dONLNdˇˇ(≤Z    wordTable°dONLNdˇˇ+$
  5492. dcb.b°dONLNdˇˇ)H    256,break°dONLNdˇˇ(Δ~setByte°dONLNdˇˇ)HwordTable,nonBreak,$ca°dONLNdˇˇ(–~setByte°dONLNdˇˇ)H-wordTable,letter,('A','Z'),('a','z')('Ä','ü')°dONLNdˇˇ(⁄~setByte°dONLNdˇˇ)H.wordTable,letter,'Æ','Ø','æ','ø',('À','œ'),'ÿ'°dONLNdˇˇ(‰~setByte°dONLNdˇˇ)HwordTable,midLetter,'-'°dONLNdˇˇ(Ó~setByte°dONLNdˇˇ)HwordTable,midLetNum,$27,'’'°dONLNdˇˇ(¯~setByte°dONLNdˇˇ)HwordTable,number,('0','9')°dONLNdˇˇ(~setByte°dONLNdˇˇ)H wordTable,preNum,'$','¢','£','¥'°dONLNdˇˇ( ~setByte°dONLNdˇˇ)HwordTable,postNum,'%'°dONLNdˇˇ(~setByte°dONLNdˇˇ)HwordTable,midNum,','°dONLNdˇˇ( ~setByte°dONLNdˇˇ)HwordTable,preMidNum,'.'°dONLNdˇˇ(*~setByte°dONLNdˇˇ)HwordTable,blank,$00,' ',$09°dONLNdˇˇ(4~setByte°dONLNdˇˇ)HwordTable,cr,$0d°dONLNdˇˇ(>~endWith°dONLNdˇˇ(HZ=;============================================================
  5493. °dONLNdˇˇ*The character triple °dONLNdˇˇ)cGtable is a coded representation of a list of continuation sequences. It°dONLNdˇˇ(kZ!consists of a list of packed one °dONLNdˇˇ)õ9word triples, preceded by a length word. This length word°dONLNdˇˇ(wZ]contains the number of triples minus one. Each triple contains three character types, either °dONLNdˇˇ(was°dONLNdˇˇ(ÑZderived from the °dONLNdˇˇ)QcharType°dONLNdˇˇ)8 table or the special type °dONLNdˇˇ)twild°dONLNdˇˇ) (= zero). The three types °dONLNdˇˇ){ in a triple°dONLNdˇˇ(êZ\are packed into fields five bits apiece, with the most significant bit in the word cleared. °dONLNdˇˇ(ê The°dONLNdˇˇ(úZ)first type in the triple is the leftmost.°dONLNdˇˇ*OA continuation sequence of length three (xyz) is represented by entering three °dONLNdˇˇ(¥’triples into the°dONLNdˇˇ(¿ZZtriple list: xyz, *xy, and yz* (where ‘*’ stands for the type wild, which is always zero).†Ç
  5494. œm 
  5495. 4‰ù˜À8°ñ°öˇ˝†ò<õ<õ°dONLNdˇˇ+J1hyphen†ô†ó4‰ ˜¯8°ñ°öˇ˝ †ò°dONLNdˇˇ)3letter†ô†ó†å4“uÂ84“´ÂŸ8
  5496. "Dà"Dà4“uÂ8†ç°ñ°öˇ˝†ò°dONLNdˇˇ(flÖhyphen†ô†ó°ñ°öˇ˝ †ò°dONLNdˇˇ)2letter†ô†ó°ñ°öˇ˝
  5497. †ò°dONLNdˇˇ).wild†ô†ó†å
  5498. 4‰u˜84‰´˜Ÿ8
  5499. "Dà"Dà4‰u˜8†ç°ñ°öˇ˝ †ò°dONLNdˇˇ(Òãletter†ô†ó°ñ°öˇ˝†ò°dONLNdˇˇ)&hyphen†ô†ó°ñ°öˇ˝ †ò°dONLNdˇˇ)3letter†ô†ó†å
  5500. 4ˆu    84ˆ´    Ÿ8
  5501. "Dà"Dà4ˆu    8†ç°ñ°öˇ˝
  5502. †ò°dONLNdˇˇ(åwild†ô†ó°ñ°öˇ˝ †ò°dONLNdˇˇ)+letter†ô†ó°ñ°öˇ˝†ò°dONLNdˇˇ)'hyphen†ô†ó
  5503. 4‰p˜û8°ñ°öˇ˝ †ò°dONLNdˇˇ(Ò}letter†ô†ó
  5504. ˇˇˇˇˇˇˇˇ4ÍÚZ†††•ÑXflC˚pflCDˇ‡CGˇ·DFGJˇ‚FGJNˇ„GINQˇ‰IJQTˇÂJLTXˇÊLMX[ˇÁMO[_ˇËOP_bˇÈPRbeˇÍRSeiˇÎSUilˇÏUVloˇÌVWopˇÓVWmpˇÔTVjmˇSTfjˇÒQScfˇÚPQ`cˇÛNP\`ˇÙMNY\ˇıKMUYˇˆJKRUˇ˜HJORˇ¯GHKOˇ˘EGHKˇ˙DHˇ˚DEˇˇ    "flB#Î#/Ú#—Ú†°†É
  5505. IR°dONLNdˇˇ( Z+A continuation sequence of length two (xy) °dONLNdˇˇ)œ6is represented by entering two triples into this list:°dONLNdˇˇ(,ZU*xy, and xy*. A continuation sequence of length one has no entry in the triple list: °dONLNdˇˇ(,‡
  5506. the character°dONLNdˇˇ(9Ztype is simply °dONLNdˇˇ)E nonBreaking°dONLNdˇˇ)M.†Ç
  5507. HÑrÚ
  5508. 4K_^    ˇˇˇˇˇˇˇˇ84Kï^√8°ñ°öˇ˝ †ò*n*n°dONLNdˇˇ+µletter†ô†ó°ñ°öˇ˝
  5509. †ò°dONLNdˇˇ)/wild†ô†ó
  5510. "Dà"Dà4K_^i8°ñ°öˇ˝ †ò°dONLNdˇˇ(Xuletter†ô†ó†å
  5511. 4]_p84]ïp√8
  5512. "Dà"Dà4]_pi8†ç°ñ°öˇ˝
  5513. †ò°dONLNdˇˇ+wild†ô†ó°ñ°öˇ˝ †ò°dONLNdˇˇ)+letter†ô†ó°ñ°öˇ˝ †ò°dONLNdˇˇ)-letter†ô†ó
  5514. 4Tágµ8°ñ°öˇ˝ †ò°dONLNdˇˇ(aîletter†ô†ó4T¥g‚8°ñ°öˇ˝ †ò°dONLNdˇˇ)-letter†ô†ó
  5515. ˇˇˇˇˇˇˇˇ4ZÎbD†††•ÑXO-kZO-.ˇP-1ˇQ.014ˇR0148ˇS138;ˇT34;>ˇU46>BˇV67BEˇW79EIˇX9:ILˇY:<LOˇZ<=OSˇ[=?SVˇ\?@VYˇ]@AYZˇ^@AWZˇ_>@TWˇ`=>PTˇa;=MPˇb:;JMˇc8:FJˇd78CFˇe57?Cˇf45<?ˇg249<ˇh1259ˇi/125ˇj.2ˇk./ˇˇ    "O,#Î#/Ú#—Ú†°†É
  5516. IR°dONLNdˇˇ(àZNote that the type °dONLNdˇˇ)Vwild°dONLNdˇˇ)< cannot appear as the middle element of a triple. The words °dONLNdˇˇ(àÂ
  5517. in the triple°dONLNdˇˇ(îZKtable must be sorted in ascending numerical order for future compatibility.°dONLNdˇˇ*PThe following is an example of how a character triple table could be coded. The °dONLNdˇˇ(≠ÚdefSeq°dONLNdˇˇ(πZmacro takes a continuation °dONLNdˇˇ)ÄEsequence as a parameter, and enters a set of triples into an internal°dONLNdˇˇ(ΔZ array. The °dONLNdˇˇ)6dumpSeq°dONLNdˇˇ)1C macro sorts the triples, and stores them in the proper order with °dONLNdˇˇ(Δdc.w    ˇˇˇˇˇˇˇˇ ◊X◊
  5518. (ÏZ"How to Construct Word-Break Tables(Ï3) of 4ˇ
  5519. R◊#ˇ ˇˇˇˇ#◊ 
  5520. IR,Times
  5521. .+6-Macintosh Technical Notes /4/˘
  5522. °dONLNdˇˇ*commands.  Once again, °dONLNdˇˇ)xwriting the macros ,
  5523. Courier°dONLNdˇˇ)^defSeq°dONLNdˇˇ)* and °dONLNdˇˇ)dumpSeq°dONLNdˇˇ)1 is left as an exercise for°dONLNdˇˇ(R6 the reader.
  5524.     °dONLNdˇˇ*=;============================================================°dONLNdˇˇ+$
  5525. with°dONLNdˇˇ)H charWordRec°dONLNdˇˇ(}ZdefSeq°dONLNdˇˇ)H
  5526. letter,letter°dONLNdˇˇ(áZdefSeq°dONLNdˇˇ)Hletter,preMidNum,letter°dONLNdˇˇ(ëZdefSeq°dONLNdˇˇ)Hletter,midLetter,letter°dONLNdˇˇ(õZdefSeq°dONLNdˇˇ)Hletter,midLetNum,letter°dONLNdˇˇ(ØZdefSeq°dONLNdˇˇ)H
  5527. number,number°dONLNdˇˇ(πZdefSeq°dONLNdˇˇ)H
  5528. number,letter°dONLNdˇˇ(√ZdefSeq°dONLNdˇˇ)Hnumber,midNum,number°dONLNdˇˇ(ÕZdefSeq°dONLNdˇˇ)Hnumber,midLetNum,number°dONLNdˇˇ(◊ZdefSeq°dONLNdˇˇ)Hnumber,preMidNum,number°dONLNdˇˇ(·ZdefSeq°dONLNdˇˇ)Hnumber,postNum°dONLNdˇˇ(ÎZdefSeq°dONLNdˇˇ)H
  5529. preNum,number°dONLNdˇˇ(ıZdefSeq°dONLNdˇˇ)HpreMidNum,number°dONLNdˇˇ(    ZdefSeq°dONLNdˇˇ)H blank,blank°dONLNdˇˇ(ZdefSeq°dONLNdˇˇ)Hblank,cr°dONLNdˇˇ(ZendWith°dONLNdˇˇ(16=;============================================================°dONLNdˇˇ+$
  5530. dc.w°dONLNdˇˇ)$((wordEnd-wordBegin)/2)-1°dONLNdˇˇ)ê; length word.°dONLNdˇˇ(E6    wordBegin°dONLNdˇˇ+$
  5531. dumpSeq°dONLNdˇˇ(Y6wordEnd°dONLNdˇˇ*
  5532. =;============================================================
  5533. °dONLNdˇˇ*    A series °dONLNdˇˇ)+Qof blanks should generally select as a single word. Make certain, however, that a°dONLNdˇˇ(Ü6)carriage return does not continue a word °dONLNdˇˇ)¡7to the right (note how it has a separate character type°dONLNdˇˇ(í6Ofrom blank for this reason), otherwise word selection and wrapping do not work °dONLNdˇˇ(í–properly°dONLNdˇˇ(û6across paragraphs.
  5534. °dONLNdˇˇ*'
  5535. Extensions
  5536. °dONLNdˇˇ*The values 16-31 in the °dONLNdˇˇ)rJcharacter type table entry for null ($00) (the first byte in the character°dONLNdˇˇ(È6Jtype table) are reserved by Apple for future expansion. The use of one of °dONLNdˇˇ(Èëthese values indicates°dONLNdˇˇ(ı6=the presence of a supplementary table after the triple table.°dONLNdˇˇ*0Further Reference: (4(˘°dONLNdˇˇ+
  5537. •°dONLNdˇˇ)The Script Manager ◊4◊˘
  5538. (Ï64) of 4(Ïb"How to Construct Word-Break Tablesˇ